C++ Windows环境下实现文件下载的两种方法

季宁
季宁
发布时间:2026-10-14 | 6人浏览过
原创

本文介绍在C++中如何通过Windows API实现文件下载,涵盖基于URLDownloadToFile的简单调用和基于WinInet库的手动读写方案,包含完整代码示例。

结果或目标

在Windows平台下,使用C++将远程HTTP资源下载到本地指定路径。本文将展示两种典型的实现路径:直接下载法和流式读写法。

准备条件

  • 操作系统:Windows
  • 开发环境:支持MFC或标准Windows API编译的C++项目(如Visual Studio)
  • 依赖库:UrlMon.lib 和 WinInet.lib

真实操作顺序

第1步:引入必要头文件与链接库

目的:加载Windows下载功能所需的API声明。

  • 入口:源文件顶部
  • 动作:添加头文件引用并链接静态库。
  • 重要参数:
    • #include <UrlMon.h>
    • #include <WinInet.h>
    • #pragma comment(lib,"wininet") // 链接WinInet库

第2步:方法一 - 使用 URLDownloadToFile 快速下载

目的:最简单的方式下载单个文件,适合无需复杂Header控制的场景。

  • 入口:触发下载的函数(如按钮点击事件)
  • 动作:调用URLDownloadToFile函数。
  • 重要参数:
    • pCaller: NULL(通常传空)
    • szURL: 远程下载地址字符串
    • szFileName: 本地保存路径(需确保目录存在)
    • reserved: 0
    • pfnCB: NULL(不使用回调)
  • 完成状态:返回值等于 S_OK 表示成功,否则失败。
void DownloadSimple() {
    HRESULT hRet = URLDownloadToFile(
        NULL,
        "http://www.baidu.com/img/baidu_sylogo1.gif",
        "c:\\temp\\1.gif",
        0,
        NULL
    );
    
    if (S_OK != hRet) {
        MessageBox(NULL, _T("下载失败"), _T("Error"), MB_ICONERROR);
        return;
    }
    MessageBox(NULL, _T("下载成功"), _T("Success"), MB_ICONINFORMATION);
}

第3步:方法二 - 使用 WinInet 库手动读写

目的:需要自定义请求头、代理设置或处理大文件时的通用方案。

  • 入口:触发下载的函数
  • 动作:依次打开会话、打开URL、循环读取数据、写入文件、关闭句柄。
  • 关键步骤:
  1. 初始化会话:调用 InternetOpen。
    - agentName: 用户代理标识
    - dwAccessType: INTERNET_OPEN_TYPE_PRECONFIG(使用系统代理配置)
  2. 打开URL:调用 InternetOpenUrl。
    - 注意设置标志位如 INTERNET_FLAG_DONT_CACHE 避免本地缓存干扰。
  3. 读取与写入:创建本地文件句柄 fopen,使用 while 循环配合 InternetReadFile 和 fwrite。
    - 缓冲区大小:例如 1024字节
    - 读取数量:dwNum
  4. 清理资源:必须按逆序关闭文件和Internet句柄,防止内存泄漏。
  • 代码实现:
  • void DownloadWithWinInet() {
        // 1. 初始化Internet会话
        HINTERNET hSession = InternetOpen(
            "MyApp/1.0", 
            INTERNET_OPEN_TYPE_PRECONFIG, 
            NULL, NULL, 0
        );
        
        if (!hSession) return;
    
        // 2. 打开URL
        HINTERNET hLink = InternetOpenUrl(
            hSession, 
            "http://www.baidu.com/img/baidu_sylogo1.gif", 
            NULL, 0, 
            INTERNET_FLAG_RELOAD, 
            0
        );
    
        if (!hLink) {
            InternetCloseHandle(hSession);
            return;
        }
    
        // 3. 创建本地文件用于接收数据
        FILE* hFile = fopen("c:\\temp\\2.gif", "wb");
        if (!hFile) {
            InternetCloseHandle(hLink);
            InternetCloseHandle(hSession);
            return;
        }
    
        // 4. 循环读取并写入
        BYTE temp[1024];
        DWORD dwNum = 1; // 初始设为非0以进入循环
    
        while (dwNum > 0) {
            // 尝试读取数据
            if (!InternetReadFile(hLink, temp, sizeof(temp), &dwNum)) {
                break; // 发生错误则退出
            }
            // 如果有数据,写入文件
            if (dwNum > 0) {
                fwrite(temp, sizeof(char), dwNum, hFile);
            }
        }
    
        // 5. 清理资源
        fclose(hFile);
        InternetCloseHandle(hLink);
        InternetCloseHandle(hSession);
    
        MessageBox(NULL, _T("download finished..."), _T("Info"), MB_ICONINFORMATION);
    }

    完成判断

    • 方法一:检查 URLDownloadToFile 返回值是否为 S_OK。
    • 方法二:循环中 dwNum 最终变为 0 且无错误发生,本地文件大小与预期一致。

    简要总结

    C++在Windows下进行文件下载主要依赖系统级API。URLDownloadToFile 适合极简场景,而 WinInet 提供了更细粒度的控制能力,适用于需要认证、代理或进度监控的复杂应用。在实际项目中,请确保目标目录存在,并注意关闭所有打开的句柄以避免资源泄露。以上就是C++实现文件下载的详细内容,更多关于C++网络编程的资料请关注本站其它相关文章!

    相关标签:

    本站声明

    本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

    Python 相关产品和应用

    全部下载

    专题列表