首先当然是利用Wininet.lib库了,添加头文件#include "WinInet.h"和库#pragma comment(lib,"Wininet.lib"),
本人最开始时使用同步下载,但是发现下载600K左右的文件都不能下下来,网络自己会断掉,很奇怪,于是我采用异步方式。
#include "stdafx.h"
#include "WinInet.h"
#pragma comment(lib,"Wininet.lib")
void CALLBACK InternetProc(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength);
void test()
{
char *buffer = new char[2024] ;
hConnectedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hRequestOpenedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
hRequestCompleteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hSession = InternetOpen(L"ttt", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, INTERNET_FLAG_ASYNC);
// asynchronous transfer mode
if (m_hSession == NULL)
{
printf("Internet open error!");
return;
}
if(InternetSetStatusCallback(m_hSession, (INTERNET_STATUS_CALLBACK)InternetProc)
== INTERNET_INVALID_STATUS_CALLBACK)
{
printf("创建回调失败!");
}
m_hConnection = InternetConnect(m_hSession, L"dt.163.com", 80,L"",L"",INTERNET_SERVICE_HTTP, 0, 1);
if (m_hConnection == NULL)
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf( "InternetConnect failed, error " );
return;
}
WaitForSingleObject(hConnectedEvent, INFINITE);
}
m_hRequest = HttpOpenRequest(m_hConnection,L"GET",L"/images/news/0605/news02053101_5.jpg",
HTTP_VERSION, NULL, 0, INTERNET_FLAG_DONT_CACHE, 2); //HTTP_VERSION "HTTP/1.0"
if (m_hRequest == NULL)
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("InternetRequest Failure!");
return;
}
// Wait until we get the request handle
WaitForSingleObject(hRequestOpenedEvent, INFINITE);
}
BOOL bSendRequest = HttpSendRequest(m_hRequest, NULL, 0, 0, 0);
if (bSendRequest == FALSE)
{
printf("SendRequest Failure!");
}
WaitForSingleObject(hRequestCompleteEvent, INFINITE);
BOOL hwrite;
DWORD written;
HANDLE createfile;
createfile=CreateFile(L"//sss.jpg",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if (createfile==INVALID_HANDLE_VALUE)
{
printf("Create jpg error!");
return;
}
TCHAR bufQuery[32] = {0};
DWORD dwLengthBufQuery = sizeof(bufQuery);
HttpQueryInfo(m_hRequest, HTTP_QUERY_CONTENT_LENGTH, bufQuery, &dwLengthBufQuery, NULL);
DWORD dwFileSize = (DWORD)_wtol(bufQuery); //get the length of received file
printf("%d/n",dwFileSize);
DWORD dwBytesRead;
while(1)
{
InternetReadFile(m_hRequest,buffer,sizeof(buffer),&dwBytesRead);
if(dwBytesRead == 0)
break;
hwrite=WriteFile(createfile,buffer,sizeof(buffer),&written,NULL);
if (hwrite==0)
{
printf("Write error!");
break ;
}
}
delete buffer;
CloseHandle(createfile);
InternetCloseHandle(m_hSession);
InternetCloseHandle(m_hConnection);
InternetCloseHandle(m_hRequest);
}
void CALLBACK InternetProc(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus,
LPVOID lpStatusInfo, DWORD dwStatusInformationLength)
{
printf( "Callback dwInternetStatus: %d/r" , dwInternetStatus);
switch(dwContext)
{
case 1: // Connection handle
if (dwInternetStatus == INTERNET_STATUS_HANDLE_CREATED)
{
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
m_hConnection = (HINTERNET)pRes->dwResult;
printf( "Connect handle created/n");
SetEvent(hConnectedEvent);
}
break;
case 2: // Request handle
switch(dwInternetStatus)
{
case INTERNET_STATUS_HANDLE_CREATED:
{
INTERNET_ASYNC_RESULT *pRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
m_hRequest = (HINTERNET)pRes->dwResult;
printf( "Request handle created/n");
SetEvent(hRequestOpenedEvent);
}
break;
case INTERNET_STATUS_REQUEST_SENT:
{
DWORD *lpBytesSent = (DWORD*)lpStatusInfo;
printf("Bytes Sent: %d/n", *lpBytesSent);
//dwNumBytesComplete += *lpBytesSent;
}
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
{
INTERNET_ASYNC_RESULT *pAsyncRes = (INTERNET_ASYNC_RESULT *)lpStatusInfo;
printf("Function call finished" );
printf("dwResult: %d/n" ,pAsyncRes->dwResult);
printf( "dwError: %s/n ",pAsyncRes->dwError);
SetEvent(hRequestCompleteEvent);
}
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
printf("Receiving Response/n" );
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
{
DWORD *dwBytesReceived = (DWORD*)lpStatusInfo;
printf( "Received %d/n " , *dwBytesReceived);
}
}
}
}
代码中用一个回调函数来控制每一步是否完成,功能是下载一幅图片。
如果要想程序有断点下载功能,其实很简单,在使用HttpSendRequest发送请求之前,只需要在发送请求之前添加头信息:Range:bytes=1000-,则服务器会从文件的1000byte处开始传送文件直到结束,如果想下载文件的某一部分,则可使用Range:bytes=1000-2000。
TCHAR szSize[MAX_PATH] = {0}; //using this Content-Type POST == GET
// printf("file length222222 = %d/n", dwSizeExist);
wsprintf (szSize, L"Range:bytes=%d-", dwSizeExist);
HttpAddRequestHeaders(m_hRequest,
szSize,
-1,
HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
下面是上传代码,注意HttpAddRequestHeaders,它用来添加头信息,比如你上传的文件类型,编码方式等,我这里是因为文本文件采用了utf-8编码,所以才添加此头信息。具体类型根据自己情况来,也可参考http头信息
BOOL UploadFile( TCHAR *szFileName)
{
BOOL retVal = FALSE;
m_hSession = NULL;
m_hConnection = NULL;
m_hRequest = NULL;
char buffer [1024] = {0} ;
HANDLE createfile;
createfile=CreateFile(szFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if (createfile==INVALID_HANDLE_VALUE)
{
return retVal;
}
m_hSession = InternetOpen(HTTP_USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (m_hSession == NULL)
{
//printf("Internet open error!");
CloseHandle(createfile);
return retVal;
}
m_hConnection = InternetConnect(m_hSession, SERVER_IP, SERVER_PORT,L"",L"",INTERNET_SERVICE_HTTP, 0, 0);
if (m_hConnection == NULL)
{
//printf("InternetConnection Failure!");
InternetCloseHandle(m_hSession);
CloseHandle(createfile);
return retVal;
}
LPCTSTR accept[] = {
_T("*/*"),
NULL
};
m_hRequest = HttpOpenRequest(m_hConnection,L"POST",UPLOAD_CONTACTLIST_WEB,
HTTP_VERSION_1_1, NULL, accept, INTERNET_FLAG_DONT_CACHE, 0);
if (m_hRequest == NULL)
{
//printf("InternetRequest Failure!");
InternetCloseHandle(m_hSession);
InternetCloseHandle(m_hConnection);
CloseHandle(createfile);
return retVal;
}
TCHAR szContentType[] = L"Content-Type:application/x-www-form-urlencoded;charset=utf-8/r/n"; //using this Content-Type POST == GET
HttpAddRequestHeaders(m_hRequest,
szContentType,
-1,
HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
DWORD dwRead;
DWORD nBytesRead;
INTERNET_BUFFERS BufferIn = {0};
FillMemory(&BufferIn, sizeof(BufferIn), 0);
BufferIn.dwBufferTotal = GetFileSize (createfile, NULL);
//这里是你要传送数据的总大小,比如一个文件的大小::GetFileSize(hFile, 0)
BufferIn.dwStructSize = sizeof(INTERNET_BUFFERS);
BufferIn.dwBufferLength = sizeof(buffer);
//分次上传的话,每次上传数据的大小,比如4里面的dwBufSize
if(!HttpSendRequestEx( m_hRequest, &BufferIn, NULL, HSR_INITIATE, 0))
{
//printf( "Error on HttpSendRequestEx %lu/n",GetLastError() );
InternetCloseHandle(m_hSession);
InternetCloseHandle(m_hConnection);
InternetCloseHandle(m_hRequest);
CloseHandle(createfile);
return retVal;
}
BOOL hwrite = FALSE; //check read file whether success!
while (1)
{
nBytesRead = 0;
hwrite=ReadFile(createfile,buffer,sizeof(buffer),&nBytesRead,NULL);
if (hwrite)
{
if (nBytesRead != 0)
{
dwRead = 0;
if (InternetWriteFile(m_hRequest, buffer, nBytesRead, &dwRead))
{
//printf("Send File length:%d !/n",dwRead);
}
}
else
{
//printf("Send File over!");
break;
}
}
}
if(!HttpEndRequest(m_hRequest, NULL, 0, 0))
{
printf( "Error on HttpEndRequest %lu /n", GetLastError());
InternetCloseHandle(m_hSession);
InternetCloseHandle(m_hConnection);
InternetCloseHandle(m_hRequest);
CloseHandle(createfile);
return retVal ;
}
LPSTR lpszData; //buffer for the data
DWORD dwSize; //size of the data available
DWORD dwDownloaded;
FILE *hResult = NULL;
TCHAR szResultFileName[MAX_PATH] = {0};
GetModuleFileName(NULL, szResultFileName, MAX_PATH);
AslGetFilePath(szResultFileName);
wcscat(szResultFileName, L"result.json");
hResult = _tfopen(szResultFileName,L"wb");//use to check whether Upload succeed.
if (hResult == NULL)
{
AslWriteLog("Create result.json File error!");
}
while(1)
{
// The call to InternetQueryDataAvailable determines the amount of
// data available to download.
if (!InternetQueryDataAvailable(m_hRequest,&dwSize,0,0))
{
//printf("NO RESPONSE!");
break;
}
else
{
// Allocates a buffer of the size returned by InternetQueryDataAvailable
lpszData = new char[dwSize+1];
// Reads the data from the HINTERNET handle.
if(!InternetReadFile(m_hRequest,(LPVOID)lpszData,dwSize,&dwDownloaded))
{
delete[] lpszData;
break;
}
else
{
if (dwDownloaded == 0)
{
break;
}
// Adds a null terminator to the end of the data buffer
fwrite(lpszData, 1, dwSize,hResult);
// Delete the two buffers
delete[] lpszData;
// Check the size of the remaining data. If it is zero, break.
}
}
}
if(hResult !=NULL)
{
fclose(hResult);
if (JsonTanslate(szResultFileName))
{
retVal = TRUE;
}
hResult = NULL;
}
CloseHandle(createfile);
InternetSetStatusCallback( m_hSession, NULL );
InternetCloseHandle(m_hSession);
InternetCloseHandle(m_hConnection);
InternetCloseHandle(m_hRequest);
return retVal;
}