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

MFC 實現網頁下載與儲存:CInternetSession 封裝 GetSourceHtml 函式完整指南

     編輯:關於C語言

利用 MFC WinInet 類別(CInternetSession、CInternetFile、CStdioFile)即可輕鬆實現「輸入 URL → 下載 HTML → 儲存檔案」的完整流程。本文封裝通用函式 GetSourceHtml,處理例外、編碼、大檔分塊寫入,並示範進度顯示與編碼轉換技巧。

核心函式:GetSourceHtml

BOOL GetSourceHtml(const CString& strUrl, const CString& strSavePath)
{
    CInternetSession session(_T("MyDownloader"), 1, 
                             PRE_CONFIG_INTERNET_ACCESS, NULL, NULL, 0);
    CInternetFile* pFile = NULL;

    try {
        // 1. 開啟 URL (支援 HTTP/HTTPS/FTP)
        pFile = (CInternetFile*)session.OpenURL(strUrl, 1, 
            INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE);
    }
    catch (CInternetException* pEx) {
        pEx->GetErrorMessage(m_strError.GetBuffer(256), 256);
        m_strError.ReleaseBuffer();
        pEx->Delete();
        return FALSE;
    }

    if (!pFile) return FALSE;

    // 2. 開啟本地檔案 (文字模式自動處理換行)
    CStdioFile fileLocal;
    if (!fileLocal.Open(strSavePath, 
        CFile::modeCreate | CFile::modeWrite | CFile::typeText)) {
        delete pFile;
        return FALSE;
    }

    // 3. 迴圈讀寫 (ReadString 自動處理緩衝)
    CString strLine;
    while (pFile->ReadString(strLine)) {
        fileLocal.WriteString(strLine + _T("\n")); // 保留換行
    }

    // 4. 清理
    fileLocal.Close();
    delete pFile;
    session.Close();
    return TRUE;
}

關鍵細節解析

1. CInternetSession 參數

  • dwContext:非同步回調識別碼,同步模式傳 1 即可。
  • dwAccessType:PRE_CONFIG_INTERNET_ACCESS 自動使用系統 Proxy 設定(IE/Edge 設定)。
  • OpenURL 旗標:INTERNET_FLAG_RELOAD 強制重新下載,INTERNET_FLAG_DONT_CACHE 避免快取污染。

2. 編碼處理:UTF-8 → Unicode

網頁多為 UTF-8,MFC CString (Unicode 建置) 需轉換:

// 讀取原始位元組
CByteArray rawData;
BYTE buf[4096];
UINT nRead;
while ((nRead = pFile->Read(buf, 4096)) > 0) {
    rawData.Append(buf, nRead);
}

// UTF-8 轉 Unicode
int nChars = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)rawData.GetData(), 
                                 rawData.GetSize(), NULL, 0);
CStringW unicodeStr;
MultiByteToWideChar(CP_UTF8, 0, (LPCCH)rawData.GetData(), 
                    rawData.GetSize(), unicodeStr.GetBuffer(nChars), nChars);
unicodeStr.ReleaseBuffer();

// 寫入 Unicode 文字檔
CStdioFile file(strSavePath, CFile::modeCreate|CFile::modeWrite|CFile::typeText);
file.WriteString(unicodeStr);

3. 大檔案進度回報

// 取得 Content-Length
CString strLen;
pFile->QueryInfo(HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &strLen);
ULONGLONG total = _ttoi64(strLen);
ULONGLONG downloaded = 0;

BYTE buf[8192];
while ((nRead = pFile->Read(buf, 8192)) > 0) {
    fileLocal.Write(buf, nRead); // 二進位寫入
    downloaded += nRead;
    int percent = total ? (int)(downloaded * 100 / total) : 0;
    pDlg->PostMessage(WM_DOWNLOAD_PROGRESS, percent, 0);
}

4. 例外處理最佳實務

catch (CInternetException* pEx) {
    TCHAR szErr[256];
    pEx->GetErrorMessage(szErr, 255);
    TRACE(_T("下載失敗: %s (Error 0x%X)\n"), szErr, pEx->m_dwError);
    pEx->Delete();
    return FALSE;
}
catch (CFileException* pEx) {
    // 本地檔案寫入錯誤 (磁碟滿、權限...)
    pEx->Delete();
    return FALSE;
}
catch (CMemoryException* pEx) {
    // 記憶體不足
    pEx->Delete();
    return FALSE;
}

完整封裝類別:CHtmlDownloader

class CHtmlDownloader {
public:
    // 同步下載
    static BOOL Download(LPCTSTR url, LPCTSTR savePath, 
                         CWnd* pProgressWnd = NULL, UINT msgProgress = 0);

    // 非同步下載 (工作者執行緒)
    static UINT AFX_CDECL AsyncDownload(LPVOID pParam);

    struct AsyncParam {
        CString url, savePath;
        CWnd* pWnd; UINT msg;
        BOOL bResult; CString error;
    };
};

應用場景

執行畫面

網頁下載儲存程式介面

圖:輸入 URL、儲存路徑,即時顯示下載進度與內容預覽

總結

MFC WinInet 類別提供了高層、物件導向的網路存取介面,GetSourceHtml 函式封裝了「開啟會話 → 開啟 URL → 串流讀寫 → 例外安全」的標準模式。掌握編碼轉換、進度回報、大檔分塊、同步/非同步兩種模式,即可應對從簡單網頁存檔到複雜爬蟲/更新器的各種需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景關鍵設定
離線瀏覽/歸檔遞迴解析 HTML 中的 href/src,批次下載資源
網頁異動監控定時下載、計算雜湊值比對、差異通知
資料擷取/爬蟲搭配正則表達式/HTML Parser (如 Gumbo) 提取結構化資料
軟體自動更新下載版本資訊 XML/JSON,比對後下載安裝包