URLDownloadToFile (位於 Urlmon.dll, 引入 Urlmon.lib) 是 Windows 提供的高層下載 API,支援 HTTP/HTTPS/FTP、自動處理 Proxy、重導向、斷點續傳 (需自行實作 Range)、進度回呼。適合簡單下載需求,無需手寫 WinInet/Socket 代碼。
#include
#include
#include
#pragma comment(lib, "urlmon.lib")
// 進度回呼介面實作 (可選)
class DownloadCallback : public IBindStatusCallback {
LONG m_ref = 1;
public:
STDMETHODIMP QueryInterface(REFIID riid, void** ppv) {
if (riid == IID_IUnknown || riid == IID_IBindStatusCallback) {
*ppv = this; AddRef(); return S_OK;
}
*ppv = nullptr; return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_ref); }
STDMETHODIMP_(ULONG) Release() {
ULONG r = InterlockedDecrement(&m_ref);
if (r == 0) delete this;
return r;
}
STDMETHODIMP OnProgress(ULONG ulProgress, ULONG ulProgressMax,
ULONG ulStatusCode, LPCWSTR szStatusText) {
if (ulProgressMax) {
int pct = ulProgress * 100 / ulProgressMax;
std::wcout << L"\r進度: " << pct << L"% (" << ulProgress << L"/" << ulProgressMax << L")";
}
return S_OK;
}
// 其他純虛函數回傳 S_OK 或 E_NOTIMPL
STDMETHODIMP OnStartBinding(DWORD, IBinding*) { return S_OK; }
STDMETHODIMP GetPriority(LONG*) { return S_OK; }
STDMETHODIMP OnDataAvailable(DWORD, DWORD, FORMATETC*, STGMEDIUM*) { return S_OK; }
STDMETHODIMP OnObjectAvailable(REFIID, IUnknown*) { return S_OK; }
STDMETHODIMP OnLowResource(DWORD) { return S_OK; }
STDMETHODIMP OnStopBinding(HRESULT, LPCWSTR) { return S_OK; }
STDMETHODIMP GetBindInfo(DWORD*, BINDINFO*) { return E_NOTIMPL; }
};
int wmain() {
DownloadCallback cb;
HRESULT hr = URLDownloadToFile(
nullptr, // pCaller
L"https://example.com/file.zip", // szURL
L"D:\\downloads\\file.zip", // szFileName
0, // dwReserved
&cb // lpfnCB
);
if (SUCCEEDED(hr))
std::wcout << L"\n下載成功!\n";
else
std::wcerr << L"\n失敗: 0x" << std::hex << hr << std::endl;
return 0;
}
pCaller:通常傳 nullptr;若在 ActiveX/IE 宿主中可傳容器 IUnknown。szURL:支援 https://, https://, ftp://, file://。szFileName:本地完整路徑,**目錄必須存在**,函數不建立目錄。dwReserved:保留,必須為 0。lpfnCB:IBindStatusCallback 指標,提供進度、暫停/繼續、驗證等控制。傳 nullptr 為靜默下載。| HRESULT | 含義 |
|---|---|
| S_OK (0) | 成功 |
| E_OUTOFMEMORY | 記憶體不足 |
| INET_E_DOWNLOAD_FAILURE | 網路/伺服器錯誤 |
| INET_E_RESOURCE_NOT_FOUND | 404 Not Found |
| E_ACCESSDENIED | 權限不足 (寫入目標/網路存取) |
| S_FALSE | 使用者取消 (回呼傳回 E_ABORT) |
OnProgress 記錄已下載位元組,重啟時需自行發送 Range 標頭 (需用 IBindStatusCallback::GetBindInfo 設定 BINDINFO 的 szExtraInfo),或改用 WinInet 手動控制。URLDownloadToFile,主執行緒保持響應。InternetSetOption 覆寫。