首页 > 其他分享 >使用WinINet实现HTTP/HTTPS下载文件

使用WinINet实现HTTP/HTTPS下载文件

时间:2023-08-01 20:34:45浏览次数:40  
标签:HTTP internet nullptr failed HTTPS address return INTERNET WinINet

环境:

  Windows平台:Windows 10 专业版(64位)、VS2019

开始:

一、工具类

class internet
{
public:
    internet(HINTERNET hInternet) : _internet(hInternet)
    {
    }
    internet(internet&);
    internet(const internet&);
    ~internet()
    {
        if (_internet) {
            InternetCloseHandle(_internet);
            _internet = nullptr;
        }
    }

    internet& operator =(HINTERNET hInternet)
    {
        _internet = hInternet;
    }
    internet& operator =(internet&);
    internet& operator =(const internet&);

    operator HINTERNET()
    {
        return _internet;
    }
    operator bool() const
    {
        return _internet != nullptr;
    }
    
protected:
    HINTERNET _internet;
};

二、HTTP下载

int download_http(const char* address, const char* path, const char* user, const char* password, const char* filename)
{
    // 创建会话
    internet hSession = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0);
    if (!hSession) {
        printf("create session failed,error=%d.", GetLastError());
        return -1; // create session failed
    }
    // 设置超时时间
    DWORD timeout = 10000;
    InternetSetOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(timeout));
    InternetSetOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, &timeout, sizeof(timeout));
    InternetSetOption(hSession, INTERNET_OPTION_SEND_TIMEOUT, &timeout, sizeof(timeout));
    // 创建连接
    internet hConnect = InternetConnectA(hSession, address, INTERNET_DEFAULT_HTTP_PORT, user, password, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) {
        printf("connect failed,address=%s,error=%d.", address, GetLastError());
        return -2; // connect failed
    }
    // 创建请求
    internet hRequest = HttpOpenRequestA(hConnect, "GET", path, HTTP_VERSION, "", nullptr, INTERNET_FLAG_KEEP_CONNECTION, 0);
    if (!hRequest) {
        printf("open request failed,address=%s%s,error=%d.", address, path, GetLastError());
        return -3; // open request failed
    }
    // 发送请求
    if (!HttpSendRequest(hRequest, nullptr, 0, nullptr, 0)) {
        printf("send request failed,address=%s%s,error=%d.", address, path, GetLastError());
        return -4; // send request failed
    }
    // 获取请求状态
    DWORD dwStatus = HTTP_STATUS_OK;
    DWORD dwStatusSize = sizeof(dwStatus);
    HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, nullptr);
    if (dwStatus != HTTP_STATUS_OK) {
        printf("http query failed,address=%s,error=%d.", address, dwStatus);
        return -5; // http query failed
    }
    // 打开文件
    std::ofstream out_file(filename, std::ios::binary);
    if (!out_file.is_open()) {
        printf("open file failed,address=%s,filename=%s,error=%d.", address, filename, GetLastError());
        return -6; // open file failed
    }
    // 下载文件
    int total = 0;
    DWORD bytes = 0;
    char buffer[1024]{ 0 };
    while (InternetReadFile(hRequest, buffer, sizeof(buffer), &bytes) && bytes > 0) {
        out_file.write(buffer, bytes);
        total += bytes;
    }
    if (total < 1) {
        printf("download file is empty,address=%s,filename=%s,size=%d.", address, filename, total);
        return -7; // download file is empty
    }
    return 0;
}

  使用:download_http("192.168.1.10", "/update/file", "user", "password", "test.txt")

三、HTTPS下载

int download_https(const char* address, const char* path, const char* user, const char* password, const char* filename)
{
    // 创建会话
    internet hSession = InternetOpenA("", INTERNET_OPEN_TYPE_DIRECT, nullptr, nullptr, 0);
    if (!hSession) {
        printf("create session failed,error=%d.", GetLastError());
        return -1; // create session failed
    }
    // 设置超时时间
    DWORD timeout = 10000;
    InternetSetOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeout, sizeof(timeout));
    InternetSetOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, &timeout, sizeof(timeout));
    InternetSetOption(hSession, INTERNET_OPTION_SEND_TIMEOUT, &timeout, sizeof(timeout));
    // 创建连接
    internet hConnect = InternetConnectA(hSession, address, INTERNET_DEFAULT_HTTPS_PORT, user, password, INTERNET_SERVICE_HTTP, 0, 0);
    if (!hConnect) {
        printf("connect failed,address=%s,error=%d.", address, GetLastError());
        return -2; // connect failed
    }
    // 创建请求
    internet hRequest = HttpOpenRequestA(hConnect, "GET", path, HTTP_VERSION, "", nullptr, INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE, 0);
    if (!hRequest) {
        printf("open request failed,address=%s%s,error=%d.", address, path, GetLastError());
        return -3; // open request failed
    }
    // 发送请求
    if (!HttpSendRequest(hRequest, nullptr, 0, nullptr, 0)) {
        int error = GetLastError();
        if (error == ERROR_INTERNET_INVALID_CA) {
            DWORD dwFlags;
            DWORD dwBuffLen = sizeof(dwFlags);
            if (InternetQueryOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, (LPVOID)&dwFlags, &dwBuffLen)) {
                dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID | SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
                InternetSetOption(hRequest, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof(dwFlags));
                if (!HttpSendRequest(hRequest, nullptr, 0, nullptr, 0)) {
                    printf("send request failed,address=%s%s,error=%d.", address, path, GetLastError());
                    return -4; // send request failed
                }
            }
        }
        else {
            printf("send request failed,address=%s%s,error=%d.", address, path, error);
            return -4; // send request failed
        }
    }
    // 获取请求状态
    DWORD dwStatus = HTTP_STATUS_OK;
    DWORD dwStatusSize = sizeof(dwStatus);
    HttpQueryInfo(hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, nullptr);
    if (dwStatus != HTTP_STATUS_OK) {
        printf("http query failed,address=%s,error=%d.", address, dwStatus);
        return -5; // http query failed
    }
    // 打开文件
    std::ofstream out_file(filename, std::ios::binary);
    if (!out_file.is_open()) {
        printf("open file failed,address=%s,filename=%s,error=%d.", address, filename, GetLastError());
        return -6; // open file failed
    }
    // 下载文件
    int total = 0;
    DWORD bytes = 0;
    char buffer[1024]{ 0 };
    while (InternetReadFile(hRequest, buffer, sizeof(buffer), &bytes) && bytes > 0) {
        out_file.write(buffer, bytes);
        total += bytes;
    }
    if (total < 1) {
        printf("download file is empty,address=%s,filename=%s,size=%d.", address, filename, total);
        return -7; // download file is empty
    }
    return 0;
}

  使用:download_https("192.168.1.10", "/update/file", "user", "password", "test.txt")

扩展:

  2)WinINet处理身份验证:https://learn.microsoft.com/zh-cn/windows/win32/wininet/handling-authentication

标签:HTTP,internet,nullptr,failed,HTTPS,address,return,INTERNET,WinINet
From: https://www.cnblogs.com/dongc/p/17596755.html

相关文章

  • C# HttpUtility.UrlEncode与 Uri.EscapeDataString区别
    相同点均是对url进行编码区别HttpUtility.UrlEncode会将空格转换为加号(+)Uri.EscapeDataString会将空格转换为%20适用场景HttpUtility.UrlEncode适用于url是查询参数Uri.EscapeDataString适用于url是作为文件路径使用......
  • 电脑Windows 10/11中如何设置HTTP代理
     嗨,亲爱的网络探索者!是否曾遇到无法访问特定网站或慢如蜗牛的网络速度?别担心!今天我将与你分享一个简单而有效的方法——设置HTTP代理,让你畅享网络的自由与速度。让我们一起来学习,在Windows10/11中如何设置HTTP代理。 第一步:找到网络设置 首先,我们需要前往电脑的网络设置......
  • spring boot学习(7)— 自定义中的 HttpMessageConverter
    在我们开发自己的应用时,有时候,我们可能需要自定义一些自己的数据格式来传输,这时,自定义的数据传输和类的实例之间进行转化就需要统一起来了, SpringMVC 中的 HttpMessageConverter 就派上用场了。HttpMessageConverter 的声明:publicinterfaceHttpMessageConverter<T>{......
  • 初探-HttpServletRequestWrapper包装类
    HttpServletRequestWrapper是JavaServletAPI中的一个类,它是一个装饰器设计模式的实现,用于扩展和包装原始的HttpServletRequest对象。通过继承HttpServletRequestWrapper类,我们可以在不修改原始请求对象的情况下,对其进行增强或修改。这个类的作用在于拦截和改变对原始Ht......
  • ServletRequest与HttpServletRequest有什么区别
    ServletRequest和HttpServletRequest是JavaServletAPI中的两个接口,它们都用于表示客户端发起的HTTP请求,但在功能和用法上有一些区别。ServletRequest接口:ServletRequest是JavaServletAPI中的基本接口,它定义了所有Servlet请求对象必须遵循的通用行为和功能。Http......
  • HttpServletRequest
    HttpServletRequest是JavaServletAPI中的一个接口,用于表示客户端的HTTP请求信息。它提供了访问客户端发送的请求的方法和属性,包括请求的URL、请求参数、请求头、会话信息、Cookie、请求方法(GET、POST等)、请求体等等。在JavaWeb应用程序中,当客户端发送HTTP请求时,Web......
  • 记一次 HTTPS 抓包分析和 SNI 的思考
    日常听说HTTPS是加密协议,那现实中的HTTPS流量,是真的完全加密吗?——答案是,不一定。原因嘛,抓个包就知道了。我们用curl命令触发一下:curl-v'https://s-api.37.com.cn/api/xxx'*Trying106.53.109.63:443...*Connectedtos-api.37.com.cn(106.53.109.63)port443......
  • 搭建一个简单的HTTP API Service( python+flask )
    1背景学习HTTP接口相关知识,为了方便,在本地搭建了一个可用的API环境用于学习和测试2环境windows10python3.10Flask2.3.2主要接口逻辑测试post方法get方法服务端请求日志代码提交至giteehttps://gitee.com/hahawa2/simple_api_demo......
  • xhttpcache
    xhttpcache/common/xevHtpdBase.cppatf1dc8df482aac98f0c3edf9e7fbad478f40f8af2·0xsky/xhttpcache(github.com) xhttpcache使用详细说明_阔野嘹歌的博客-CSDN博客......
  • 周一 http+tomcat+servlet入门
    packagecom.wzy.web;importjavax.servlet.*;importjavax.servlet.annotation.WebServlet;importjava.io.IOException;@WebServlet("/demo1")publicclassservletdemo1implementsServlet{@Overridepublicvoidinit(ServletConfigservletC......