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

WinINet 實現高效穩定的檔案下載:完整範例與細節解析

     編輯:關於C語言

在 Windows 網路應用開發中,使用 WinINet API 實現檔案下載是常見需求。本文提供一個封裝良好的 InternetGetFile 函數範例,支援進度條顯示、下載速度計算、斷點續傳基礎(需自行擴展)及錯誤處理,並詳細解析關鍵步驟。

函數原型與參數說明

UINT InternetGetFile(
    HINTERNET hOpen,          // InternetOpen 返回的會話句柄
    CHAR* szUrl,              // 下載目標 URL
    CHAR* szFileName,         // 本地儲存路徑
    HWND hwndProgress,        // 進度條對話框句柄 (可為 NULL)
    int idStatusText,         // 狀態文字靜態控制項 ID
    int idProgressBar         // 進度條控制項 ID
);

返回值:0 成功,非零為自定義錯誤碼(INTERNET_ERROR_OPENURL、INTERNET_ERROR_FILEOPEN、INTERNET_ERROR_READFILE 等)。

核心流程與關鍵點解析

1. 開啟 URL 連線:禁用快取,強制重新下載

CHAR szHead[] = "Accept: */*"; // 關鍵:若無此 Header,某些伺服器僅允許文字檔下載
hConnect = InternetOpenUrlA(hOpen, szUrl, szHead, lstrlenA(szHead),
    INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD, 0);

標誌組合確保:不使用本地快取、發送 Pragma: no-cache、強制從伺服器重新獲取。

2. 取得檔案大小:支援進度顯示

DWORD dwByteToRead = 0, dwSizeOfRq = 4;
HttpQueryInfo(hConnect, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
    &dwByteToRead, &dwSizeOfRq, NULL);

若伺服器不回傳 Content-Length(如動態生成內容),dwByteToRead 為 0,進度條改為「未知總量」模式。

3. 分塊讀取與寫入:16KB 緩衝區平衡效能與回應性

VOID* szTemp[16384]; // 16KB 緩衝區
do {
    if (!InternetReadFile(hConnect, szTemp, 16384, &dwSize)) { /* 錯誤處理 */ }
    if (!dwSize) break; // EOF
    fwrite(szTemp, 1, dwSize, pFile); // 寫入本地檔案
    dwBytes += dwSize;
    // 更新進度條與速度顯示...
} while (TRUE);

4. 即時速度計算與 UI 更新

DWORD start = timeGetTime(), end, elapsed;
// 迴圈內:
end = timeGetTime();
elapsed = end - start; if (elapsed == 0) elapsed = 10; // 避免除零
float fSpeed = (dwBytes / 1024.0f) / (elapsed / 1000.0f); // KB/s
// 格式化字串: "已下載 XX KB / 總計 YY KB @ ZZ.Z KB/s"
SendDlgItemMessageA(hwndProgress, idProgressBar, WM_USER+2, (dwBytes*100)/dwByteToRead, 0);
SetDlgItemTextA(hwndProgress, idStatusText, szStatus);

需連結 winmm.lib 並包含 mmsystem.h 以使用 timeGetTime。

5. 資源清理與錯誤處理

所有失敗路徑均需 fclose(pFile)、InternetCloseHandle(hConnect),並返回對應錯誤碼。成功時 fflush 確保緩衝區寫入磁碟。

擴展建議

  • 斷點續傳: 使用 HttpAddRequestHeaders 發送 Range: bytes=X-,配合 fseek 追加寫入。
  • HTTPS 支援: 確保 InternetOpen 使用 INTERNET_OPEN_TYPE_PRECONFIG,WinINet 自動處理 SSL/TLS 握手。
  • 非同步/多線程: 將下載邏輯移至工作執行緒,透過 PostMessage 更新 UI,避免阻塞主執行緒。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved