因为要项目中要想要实现一个软件自动更新的功能,之前是使用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. 02.Elasticsearch入门

        Elasticsearch支持Http类型的Restful风格API请求,需要打开9200端口.Elasticsearch服务会监听两个端口9200和9300,9200提供Http Restf ...

  2. [ Office 365 开发系列 ] Graph Service

    前言 本文完全原创,转载请说明出处,希望对大家有用. 通过[ Office 365 开发系列 ] 开发模式分析和[ Office 365 开发系列 ] 身份认证两篇内容的了解,我们可以开始使用Offi ...

  3. distinct用group by优化

    当数据量非常大,在同一个query中计算多个不相关列的distinct时,往往很容易出现数据倾斜现象,导致运行半天都不能得到结果. 比如以下的SQL语句(a, b, c没有相关性): select d ...

  4. util 常用方法

    C:\Program Files\Java\jdk1.8.0_171\src.zip!\java\lang\System.java /** * Returns the current time in ...

  5. echarts学习心得1---模块化单文件引入和标签式单文件引入

    一.模块化单文件引入 1. 为ECharts准备一个具备大小(宽高)的Dom(当然可以是动态生成的) <div id="main" style="height:40 ...

  6. ChromeExtension 写一个extension

    demo: https://github.com/rayshen/iExtensionDemo 使用: 1.打开扩展页面:chrome://extensions/ 2. 里面包含文件的结构是这样: 1 ...

  7. php中var_dump、var_export和print_r的用法区别

    void var_dump ( mixed $expression [, mixed $... ] )此函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值.数组将递归展开值,通过缩进显示其结 ...

  8. jquery的常用知识点

    一.用jquery寻找元素 1.选择器 基本选择器: $("*") $("#id") 用id匹配 $(".class") 用class名匹配 ...

  9. Linux Anaconda安装步骤

    首选下载wget https://repo.continuum.io/archive/Anaconda3-5.0.1-Linux-x86_64.sh 可以去官网查看适合自己的文件https://www ...

  10. 检查Linux服务器性能命令详解

    如果你的Linux服务器突然负载暴增,如何在最短时间内找出Linux性能问题所在? 通过执行以下命令,可以在1分钟内对系统资源使用情况有个大致的了解. uptime dmesg | tail vmst ...