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

CInternetSession 封裝多執行緒 HTTP 檔案下載元件

     編輯:關於VC++

前言

自行實作 HTTP 協定成本高且易出錯,MFC CInternetSession 封裝了 WinInet API,但屬半成品,需再封裝才能實用。本文分享一個支援多執行緒、進度回呼、Proxy 驗證的下載元件。

CInternetSession 基礎用法

靜態網頁下載

TRY {
    CInternetSession sess;
    DWORD dwFlag = INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD;
    CHttpFile* pF = (CHttpFile*)sess.OpenURL(strFilename, 1, dwFlag);
    ASSERT(pF);
    
    CString str;
    pF->QueryInfo(HTTP_QUERY_CONTENT_LENGTH, str);
    int nFileSize = _ttoi(str);
    
    char* p = new char[nFileSize];
    while (true) {
        int n = pF->Read(p, min(nFileSize, 8192));
        if (n <= 0) break;
        p += n; nFileSize -= n;
    }
    delete[] p; delete pF;
} CATCH_ALL(e) {} END_CATCH_ALL

動態網頁問題(ASP/PHP 回傳 Content-Length: 0)

int n = pF->GetLength();
while (n) {
    BYTE* p = new BYTE[n];
    pF->Read(p, n);
    delete[] p;
    n = pF->GetLength();
}

區分網路斷線與下載完成

if (n == 0) {
    DWORD dw;
    if (::InternetQueryDataAvailable((HINTERNET)*pF, &dw, 0, 0) && dw == 0) {
        // 真正下載完成
    }
}

多執行緒架構:用 SendMessage 避免同步鎖

執行緒內直接呼叫回呼函數易造成資源競爭,需加鎖同步。更優雅的做法:執行緒發送訊息至主視窗執行緒,Windows 訊息佇列天然序列化,等同將多執行緒轉單執行緒處理,極大降低複雜度(同事曾用於數百執行緒爬蟲,極度穩定)。

封裝介面設計(Template 類別)

template
class FCDownloadFileWndBase : public T {
public:
    FCDownloadFileWndBase() {}
    FCDownloadFileWndBase(UINT nID, CWnd* pParent) : T(nID, pParent) {}
    FCDownloadFileWndBase(UINT nID) : T(nID) {}
    
    void DownloadFile(LPCTSTR strFileURL, int nPriority = THREAD_PRIORITY_IDLE);
    
protected:
    // 必須實作:檢查最後修改時間,回傳 TRUE 續傳
    virtual BOOL DownloadFile_OnCheckTime(CString strFileURL, CString strTime) = 0;
    
    // 選擇性覆寫
    virtual void DownloadFile_OnFinished(CString strFileURL, char* pBuffer, int nLength) {}
    virtual void DownloadFile_OnProxyValidate(CString strFileURL, CString& strUsername, CString& strPassword) {}
    virtual void DownloadFile_OnError(CString strFileURL) {}
    virtual void DownloadFile_OnStartDownload(CString strFileURL) {}
    virtual void DownloadFile_OnProgress(CString strFileURL, int nNow, int nTotal) {}
};

使用方式

  1. 讓視窗類別繼承 FCDownloadFileWndBase<CDialog> 或 CFormView
  2. 實作必要的虛擬函數
  3. 呼叫 DownloadFile(url) 即可

關鍵特性

  • ✅ 自動使用 IE 連線設定(含 Proxy)
  • ✅ Proxy 需驗證時回呼 OnProxyValidate 讓使用者輸入帳密
  • ✅ 支援靜態/動態網頁、斷點續傳檢查
  • ✅ 進度即時回呼
  • ⚠️ 使用 Template 故不支援 MFC DECLARE_DYNAMIC,需移除並改用 C++ RTTI
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved