C++ WinHTTP实现文件下载

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

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

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

#define HTTP_COMPONENTSW_FIELD_LEN 512
typedef void(*DownLoadCallback)(int ContentSize, int CUR_LEN);

typedef struct _URL_INFO
{
WCHAR szScheme[HTTP_COMPONENTSW_FIELD_LEN ];
WCHAR szHostName[HTTP_COMPONENTSW_FIELD_LEN ];
WCHAR szUserName[HTTP_COMPONENTSW_FIELD_LEN ];
WCHAR szPassword[HTTP_COMPONENTSW_FIELD_LEN ];
WCHAR szUrlPath[HTTP_COMPONENTSW_FIELD_LEN ];
WCHAR szExtraInfo[HTTP_COMPONENTSW_FIELD_LEN ];
}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 = HTTP_COMPONENTSW_FIELD_LEN
lpUrlComponents.dwHostNameLength = HTTP_COMPONENTSW_FIELD_LEN
lpUrlComponents.dwPasswordLength = HTTP_COMPONENTSW_FIELD_LEN
lpUrlComponents.dwSchemeLength = HTTP_COMPONENTSW_FIELD_LEN
lpUrlComponents.dwUrlPathLength = HTTP_COMPONENTSW_FIELD_LEN
lpUrlComponents.dwUserNameLength = HTTP_COMPONENTSW_FIELD_LEN ;

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值