博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++ 使用WinHTTP实现文件下载功能
阅读量:4591 次
发布时间:2019-06-09

本文共 4168 字,大约阅读时间需要 13 分钟。

因为要项目中要想要实现一个软件自动更新的功能,之前是使用socket直接下载。但切换下载源的时候很麻烦。所以换用http方式。

网上找了很多资料,基本上就是下面几种:
1.curllib //功能强大太但太麻烦而且没必要
2.MFC自带的功能 // 项目不是使用的MFC所以舍
3.IE控件下载 // 没办法获取到进度,而且因为不能获取到总大小所以很容易下载的资源不完整。

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

#include 
#include
#include
#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");}

转载于:https://www.cnblogs.com/jkcx/p/6374026.html

你可能感兴趣的文章
C#屏幕截图
查看>>
JQuery模仿a标签的点击事件
查看>>
github hexo 搭建博客
查看>>
JS调用百度地图API获取地理位置
查看>>
BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)
查看>>
BZOJ 4260 Codechef REBXOR(字典树)
查看>>
idea使用maven逆向mybitis的文件
查看>>
宿舍助手app——个人工作第二天
查看>>
线段树(hdu 2795)
查看>>
David Sankoff 介绍学习链接
查看>>
当连续进行多个请求,并且请求的url地址相同时。放弃前面的所有请求,只执行最后一次请求。...
查看>>
[IIS]安装及使用
查看>>
[Tizen开发]基于Tizen平台的终端开发模拟器1 - Web
查看>>
Html::a 生成 method=post
查看>>
hbase知识
查看>>
ReactNative--state
查看>>
从别人的博客学习
查看>>
spring4的新特性---泛型注入
查看>>
在linux上安装MySQL数据库,并简单设置用户密码,登录MySQL
查看>>
CallBack
查看>>