因为要项目中要想要实现一个软件自动更新的功能,之前是使用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实现文件下载功能的更多相关文章

  1. JAVA文件下载功能问题解决日志

    今天给报告系统做了个下载功能,遇到了挺多问题,通过查资料一一解决了. 1.首先遇到的问题是:java后台的输出流输出之后,没有任何报错,浏览器端不弹出保存文件的对话框,原本是ajax请求到后台的con ...

  2. 解决springmvc中文件下载功能中使用javax.servlet.ServletOutputStream out = response.getOutputStream();后运行出异常但结果正确的问题

    问题描述: 在springmvc中实现文件下载功能一般都会使用javax.servlet.ServletOutputStream out = response.getOutputStream();封装 ...

  3. WebView实现文件下载功能

    WebView控制调用相应的WEB页面进行展示.安卓源码当碰到页面有下载链接的时候,点击上去是一点反应都没有的.原来是因为WebView默认没有开启文件下载的功能,如果要实现文件下载的功能,需要设置W ...

  4. Spring Boot实现文件下载功能

    我们只需要创建一个控制器(Controler)文件,即Controller目录下的File_Download.java,其完整目录如下: @Controller public class File_D ...

  5. Spring Boot入门(11)实现文件下载功能

      在这篇博客中,我们将展示如何在Spring Boot中实现文件的下载功能.   还是遵循笔者写博客的一贯风格,简单又不失详细,实用又能让你学会.   本次建立的Spring Boot项目的主要功能 ...

  6. ASP.NET网页中RAR、DOC、PDF等文件下载功能实例源代码

    以前做asp.net下载功能的时候都是采用:<a href="http://www.wang0214.com/wgcms">下载</a>的方式来实现下载. ...

  7. java web文件下载功能实现 (转)

    http://blog.csdn.net/longshengguoji/article/details/39433307 需求:实现一个具有文件下载功能的网页,主要下载压缩包和图片 两种实现方法: 一 ...

  8. 【Servlet】java web 文件下载功能实现

    需求:实现一个具有文件下载功能的网页,主要下载压缩包和图片 两种实现方法: 一:通过超链接实现下载 在HTML网页中,通过超链接链接到要下载的文件的地址 <!DOCTYPE html> & ...

  9. ASP.NET MVC 向浏览器发送文件以提供文件下载功能

    撑到大三了,结果发现周围的同学更加堕落了,尤其是某些人,表面上看起来很认真,实际上三天打鱼,两天晒网,结果一事无成,却还要抱怨学校教育失败. 为了吸取他们的教训,就算是一个小小的编码问题,我也要努力解 ...

随机推荐

  1. IE edge是怎么了??

    IE edge 怎么不能通过$.getJSON(url,function(data){ alert(''); });获取数据呢?,其他浏览器和IE的10以下版本都没问题获取到了,这是什么情况!本来是想 ...

  2. UNION WHERE

    w条件语句的作用域. SELECT * FROM ( SELECT asin, LOWER(country) AS country FROM grab_amzreviews_asins UNION D ...

  3. dstat命令--检查linux系统性能

    系统性能的相关工具:vmstat.netstat.iostat.ifstat. dstat命令可以查看虚拟内存.网络连接和接口.cpu活动.输入/输出设备等.

  4. flask建立数据模型数据类型

    https://blog.csdn.net/happyanger6/article/details/53947162 https://blog.csdn.net/happyanger6/article ...

  5. mysql 复合查询语句

    INSERT INTO runwa(rshottime,rmoney,renamecount) VALUES (CURDATE(),(select SUM(MONEY) from income whe ...

  6. java组件学习15天

    Linuxdocker redminegitlabnginxmavenkibanakafkaspringspring cloudLucene 搭建基本使用

  7. sql server 测试delete后数据空间情况

    总结结论: [1]如果是索引组织表,删除的数据空间是会被文件设置为可用状态,其他表都可以使用. [2]如果是堆表,删除数据空间也会设置为可用状态,但是只能给被删除数据的表使用. [3]truncate ...

  8. Zabbix基本功能使用手册

    Zabbix基本功能使用手册 vim /etc/zabbix/zabbix_agentd.conf 编辑agent配置文件. 指定那些服务器可以来获取数据,可用逗号隔开指定多台服务器. 这个参数表示a ...

  9. 005-maven坐标和依赖

    1.何为Maven坐标 groupId.artifactId.version.packaging.classifier 中央仓库:http://repol.maven.org/maven22.坐标详解 ...

  10. vueRouter点击打开新页签

    一.vue 路由使用 vue是单页面SPA,一般我们使用vue-router 设定路由进行页面跳转的时候,都是直接覆盖当前页面.比如,在a页面中有如下超链接 <router-link to=&q ...