首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

基於 libcurl 實現文件下載與進度條顯示(wxWidgets 跨平台示例)

     編輯:關於C++

項目背景與技術選型

項目需要實現程序自動更新功能。經調研,libcurl 作為成熟的跨平台網絡傳輸庫,支持 HTTP/HTTPS/FTP 等協議,API 靈活,適合嵌入 C++ 應用。結合 wxWidgets GUI 框架,可構建跨平台的下載對話框與進度顯示。

核心設計思路

  • 多線程協作:下載操作耗時,不能阻塞 UI 主線程。採用 wxTimer 定時觸發下載邏輯,實現「後台下載 + 前台刷新進度」的並發模型。
  • 回調驅動進度:libcurl 提供 CURLOPT_PROGRESSFUNCTION 回調,實時傳遞已下載/總大小,映射到 wxGauge 進度條。
  • 流式寫入文件:自定義 CURLOPT_WRITEFUNCTION,將數據直接寫入本地文件,避免內存緩衝大文件。

關鍵代碼結構

1. 主對話框類定義(downloadMain.h)

class downloadDialog : public GUIDialog {
public:
    downloadDialog(wxDialog* dlg);
    ~downloadDialog();
    void OnTimer(wxTimerEvent& event);  // 定時器事件處理
private:
    virtual void OnClose(wxCloseEvent& event);
    virtual void OnQuit(wxCommandEvent& event);
    virtual void OnAbout(wxCommandEvent& event);
    void downloadfile();                // 核心下載邏輯
    wxTimer* m_timerdown;               // 定時器對象
    DECLARE_EVENT_TABLE()
};

2. 事件表與初始化(downloadMain.cpp)

BEGIN_EVENT_TABLE(downloadDialog, GUIDialog)
    EVT_TIMER(TIMER_ID, downloadDialog::OnTimer)
END_EVENT_TABLE()

downloadDialog::downloadDialog(wxDialog* dlg) : GUIDialog(dlg) {
    m_timerdown = new wxTimer(this, TIMER_ID);
    m_timerdown->Start(100);  // 100ms 觸發一次
}

3. 文件寫入回調

struct FtpFile {
    const char* filename;
    FILE* stream;
};

int my_fwrite(void* buffer, size_t size, size_t nmemb, void* stream) {
    FtpFile* out = (FtpFile*)stream;
    if (out && !out->stream) {
        out->stream = fopen(out->filename, "wb");
        if (!out->stream) return -1;
    }
    return fwrite(buffer, size, nmemb, out->stream);
}

4. 進度條回調

int wxcurldav_dl_progress_func(void* ptr, double total, double now, double, double) {
    wxGauge* gauge = (wxGauge*)ptr;
    if (gauge && total > 0) {
        gauge->SetValue(int(100.0 * now / total));
    }
    return 0;  // 返回非 0 可取消傳輸
}

5. 下載主流程

void downloadDialog::downloadfile() {
    CURL* curl = curl_easy_init();
    if (!curl) return;

    FtpFile ftpfile = {"tmp.exe", NULL};
    curl_global_init(CURL_GLOBAL_DEFAULT);

    curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/update.exe");
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);

    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
    curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, wxcurldav_dl_progress_func);
    curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, m_gauge1);  // wxGauge 控件指針

    m_gauge1->SetValue(0);
    CURLcode res = curl_easy_perform(curl);
    m_gauge1->SetValue(100);

    curl_easy_cleanup(curl);
    if (ftpfile.stream) fclose(ftpfile.stream);
    curl_global_cleanup();

    m_timerdown->Stop();  // 關鍵:停止定時器防止重複執行

    if (res == CURLE_OK) {
        wxExecute("tmp.exe");  // 啟動安裝程序
        wxMessageBox("下載完成,啟動更新程序...");
    }
}

運行效果與注意事項

下載進度條界面預覽

  • 定時器間隔:100ms 平衡 UI 響應與 CPU 佔用,可根據文件大小調整。
  • 錯誤處理:生產環境需補全網絡異常、磁盤空間不足、校驗失敗等錯誤分支。
  • 跨平台編譯:需鏈接 libcurl、wxWidgets,Windows 下注意 DLL 部署。
  • 安全性:生產環境應驗證下載文件簽名/哈希,防止中間人攻擊。

擴展建議

  1. 使用 wxThread 替代 wxTimer 實現真正的後台下載線程,配合 wxPostEvent 更新 UI。
  2. 支持斷點續傳(CURLOPT_RESUME_FROM_LARGE)與多線程分段下載。
  3. 封裝為通用 Downloader 類,解耦業務邏輯與 UI 框架。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved