zoukankan      html  css  js  c++  java
  • 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")
    
    
    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
    ", 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");
    }
    
  • 相关阅读:
    <Learning How to Learn>Week One: Focused versus Diffuse Thinking
    "Principles of Reactive Programming" 之<Actors are Distributed> (2)
    "Principles of Reactive Programming" 之<Actors are Distributed> (1)
    "reactive programming"的概念
    "Principles of Reactive Programming" 之 <Persistent Actor State>学习笔记
    从List[Future[T]]到Future[List[T]]
    用IDEA调试Play工程
    Scala的Pattern Matching Anonymous Functions
    Akka的fault tolerant
    Manifest 与TypeTag
  • 原文地址:https://www.cnblogs.com/jkcx/p/6374026.html
Copyright © 2011-2022 走看看