方案一:MFC CInternetSession + CHttpFile
#include
CInternetSession session(_T("MyAgent"));
CHttpFile* pFile = NULL;
CString strHtml, line;
try {
// 關鍵:INTERNET_FLAG_DONT_CACHE 強制不走快取
pFile = (CHttpFile*)session.OpenURL(
url, 1, INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD
);
while (pFile->ReadString(line)) {
strHtml += line + _T("\n");
}
pFile->Close();
}
catch (CInternetException* e) {
TCHAR szErr[256]; e->GetErrorMessage(szErr, 255);
AfxMessageBox(szErr);
e->Delete();
}
delete pFile;
session.Close();
OpenURL 參數詳解
| 參數 | 說明 |
dwFlags | INTERNET_FLAG_DONT_CACHE 不快取、INTERNET_FLAG_RELOAD 強制重抓、INTERNET_FLAG_TRANSFER_ASCII/BINARY 編碼模式 |
pstrHeaders | 自定 HTTP Header (如 User-Agent, Cookie) |
dwHeadersLength | Header 長度 |
已知問題
- 參數超過 2 個 (含
dwFlags) 時 VC6 某版本會報錯;
- 預設行為會檢查快取,**必須顯式加
DONT_CACHE | RELOAD** 才能拿最新內容;
- 僅支援同步阻塞,大檔案/慢網路會凍結 UI。
方案二:#import + IXMLHTTPRequest
#import named_guids
using namespace MSXML2;
IXMLHTTPRequestPtr http;
HRESULT hr = http.CreateInstance(__uuidof(XMLHTTP));
if (FAILED(hr)) { AfxMessageBox(_T("需安裝 MSXML 4.0")); return; }
http->open(_T("GET"), _bstr_t(url), VARIANT_FALSE, _T(""), _T("")); // 同步
http->send();
if (http->readyState == 4) { // 完成
_bstr_t xml = http->responseText; // UTF-8 編碼 BSTR
// 需轉碼:UTF-8 → ANSI/Unicode
CStringA utf8(xml);
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
CStringW unicode; unicode.GetBufferSetLength(len);
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, unicode.GetBuffer(), len);
unicode.ReleaseBuffer();
// unicode 即為可用字串
}
編碼陷阱與解法
responseText 固定返回 **UTF-8 編碼 BSTR** (不受網頁 charset 影響);
- 直接印出會亂碼,**必須
MultiByteToWideChar(CP_UTF8, ...) 轉為 Unicode**;
- 若需二進制資料,用
responseBody (SAFEARRAY of UI1) 配合 Base64 解碼。
兩方案對比
| 維度 | CInternetSession | MSXML XMLHTTP |
| 依賴 | MFC (afxinet.dll) | MSXML 4.0+ (系統內建 XP+) |
| 非同步 | 困難 (需衍生類覆寫) | 原生支援 (async=TRUE + 事件) |
| Header 控制 | 完整 | 完整 (setRequestHeader) |
| 編碼處理 | 自動 (依 Content-Type) | **固定 UTF-8 需手動轉碼** |
| 錯誤處理 | CInternetException | HRESULT / _com_error |
| Proxy 支援 | 自動 (WinInet 設定) | 自動 (WinHTTP/WinInet) |
建議選型
- **簡單同步抓取、MFC 專案** →
CInternetSession (加 DONT_CACHE|RELOAD);
- **需非同步、精細 Header 控制、跨平台/非 MFC** →
IXMLHTTPRequest (記得 UTF-8 轉碼);
- **高效能/大量並發** → 考慮
WinHTTP (服務端) 或第三方 libcurl / cpp-httplib。