WM下进行http下载、断点下载和上传(c++)

来源:互联网 发布:阿甘正传 知乎 编辑:程序博客网 时间:2024/06/10 20:09

首先当然是利用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;

}