天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 12|回复: 0

c++ 使用WinHTTP实现文件下载功能

[复制链接]
  • TA的每日心情
    开心
    昨天 15:23
  • 签到天数: 69 天

    [LV.6]常住居民II

    410

    主题

    167

    回帖

    2704

    积分

    管理员

    积分
    2704
    发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
    因为要项目中要想要实现一个软件自动更新的功能,之前是使用socket直接下载。但切换下载源的时候很麻烦。所以换用http方式。
    网上找了很多资料,基本上就是下面几种:
    1.curllib //功能强大太但太麻烦而且没必要
    2.MFC自带的功能 // 项目不是使用的MFC所以舍
    3.IE控件下载 // 没办法获取到进度,而且因为不能获取到总大小所以很容易下载的资源不完整。

    思来想去,最后还是使用WinHTTP,比较简单快捷,而且功能上基本上都能够满足。

    #include <stdio.h>
    #include <Windows.h>
    #include <Winhttp.h>
    #pragma comment(lib,"Winhttp.lib")


    typedef void(*DownLoadCallback)(int ContentSize, int CUR_LEN);


    typedef struct _URL_INFO
    {
            WCHAR szScheme[512];
            WCHAR szHostName[512];
            WCHAR szUserName[512];
            WCHAR szPassword[512];
            WCHAR szUrlPath[512];
            WCHAR szExtraInfo[512];
    }URL_INFO, *PURL_INFO;


    void dcallback(int ContentSize, int file_size)
    {
            printf("count:%d,size:%d\n", ContentSize, file_size);
    }

    void download(const wchar_t *Url, const wchar_t *FileName, DownLoadCallback Func)
    {
            URL_INFO url_info = { 0 };
            URL_COMPONENTSW lpUrlComponents = { 0 };
            lpUrlComponents.dwStructSize = sizeof(lpUrlComponents);
            lpUrlComponents.lpszExtraInfo = url_info.szExtraInfo;
            lpUrlComponents.lpszHostName = url_info.szHostName;
            lpUrlComponents.lpszPassword = url_info.szPassword;
            lpUrlComponents.lpszScheme = url_info.szScheme;
            lpUrlComponents.lpszUrlPath = url_info.szUrlPath;
            lpUrlComponents.lpszUserName = url_info.szUserName;

            lpUrlComponents.dwExtraInfoLength =
                    lpUrlComponents.dwHostNameLength =
                    lpUrlComponents.dwPasswordLength =
                    lpUrlComponents.dwSchemeLength =
                    lpUrlComponents.dwUrlPathLength =
                    lpUrlComponents.dwUserNameLength = 512;

            WinHttpCrackUrl(Url, 0, ICU_ESCAPE, &lpUrlComponents);

            // 创建一个会话
            HINTERNET hSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0);
            DWORD dwReadBytes, dwSizeDW = sizeof(dwSizeDW), dwContentSize, dwIndex = 0;
            // 创建一个连接
            HINTERNET hConnect = WinHttpConnect(hSession, lpUrlComponents.lpszHostName, lpUrlComponents.nPort, 0);
            // 创建一个请求,先查询内容的大小
            HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"HEAD", lpUrlComponents.lpszUrlPath, L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH);
            WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
            WinHttpReceiveResponse(hRequest, 0);
            WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwContentSize, &dwSizeDW, &dwIndex);
            WinHttpCloseHandle(hRequest);

            // 创建一个请求,获取数据
            hRequest = WinHttpOpenRequest(hConnect, L"GET", lpUrlComponents.lpszUrlPath, L"HTTP/1.1", WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_REFRESH);
            WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
            WinHttpReceiveResponse(hRequest, 0);

            // 分段回调显示进度
            DWORD BUF_LEN = 1024, ReadedLen = 0;
            BYTE *pBuffer = NULL;
            pBuffer = new BYTE[BUF_LEN];

            HANDLE hFile = CreateFileW(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

            while (dwContentSize > ReadedLen)
            {
                    ZeroMemory(pBuffer, BUF_LEN);
                    WinHttpReadData(hRequest, pBuffer, BUF_LEN, &dwReadBytes);
                    ReadedLen += dwReadBytes;

                    // 写入文件
                    WriteFile(hFile, pBuffer, dwReadBytes, &dwReadBytes, NULL);
                    // 进度回调
                    Func(dwContentSize, ReadedLen);

            }

            CloseHandle(hFile);
            delete pBuffer;


            /*
            // 一次性写入整个文件
            BYTE *pBuffer = NULL;

            pBuffer = new BYTE[dwContentSize];
            ZeroMemory(pBuffer, dwContentSize);
            //do{
                    WinHttpReadData(hRequest, pBuffer, dwContentSize, &dwReadBytes);
                    Func(dwContentSize, dwReadBytes);
            //} while (dwReadBytes == 0);
           

            HANDLE hFile = CreateFileW(FileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
            WriteFile(hFile, pBuffer, dwContentSize, &dwReadBytes, NULL);
            CloseHandle(hFile);

            delete pBuffer;
            */
            WinHttpCloseHandle(hRequest);
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);

           
    }



    int main(int argc, char* argv[])
    {
            download(L"http://sw.bos.baidu.com/sw-search-sp/software/58d7820029ae7/BaiduMusic_10.1.7.7_setup.exe", L"./BaiduMusic_10.1.7.7_setup.exe", &dcallback);
            system("pause");
    }

     

     

     

     

    c++ 使用WinHTTP实现文件下载功能
    中国膜结构网打造全中国最好的膜结构综合平台 ,统一协调膜结构设计,膜结构施工,膜材采购,膜材定制,膜结构预算全方位服务。 中国空间膜结构协会合作单位。
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|

    GMT+8, 2024-7-1 05:43 , Processed in 0.056955 second(s), 22 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表