vc++实现http下载的通用类


// DownloadHttp.cpp: implementation of the CDownloadHttp class.////////////////////////////////////////////////////////////////////////
#include "stdafx.h"#include "downtest.h"#include "DownloadHttp.h"
#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif
void DownloadNotify ( int nIndex, UINT nNotityType, LPVOID lpNotifyData, LPVOID pDownloadMTR );
//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////
CDownloadHttp::CDownloadHttp(){
}
CDownloadHttp::~CDownloadHttp(){
}
BOOL CDownloadHttp::DownloadOnce(){ // 不需要下载了 int nWillDownloadSize = Get_WillDownloadSize();    // 本次应该下载的字节数 int nDownloadedSize = Get_DownloadedSize ();    // 已下载字节数 if ( nWillDownloadSize > 0 && nDownloadedSize >= nWillDownloadSize )  return DownloadEnd(TRUE);
 if ( !CDownloadPub::DownloadOnce () )  return DownloadEnd(FALSE);
 char szTailData[NET_BUFFER_SIZE] = {0}; int nTailSize = sizeof(szTailData); if ( !RequestHttpData ( TRUE, szTailData, &nTailSize ) )  return DownloadEnd(FALSE); // 从HTTP服务器中读取数据,并保存到文件中 return DownloadEnd ( RecvDataAndSaveToFile(m_SocketClient,szTailData, nTailSize) );
}
BOOL CDownloadHttp::RequestHttpData(BOOL bGet, char *szTailData/*=NULL*/, int *pnTailSize/*=NULL*/ ){ int nTailSizeTemp = 0; BOOL bRetryRequest = TRUE; while ( bRetryRequest ) {  CString csReq = GetRequestStr ( bGet );  CString csResponse;  nTailSizeTemp = pnTailSize?(*pnTailSize):0;  if ( !SendRequest ( csReq, csResponse, szTailData, &nTailSizeTemp ) )   return FALSE;
  CString csReferer_Old = m_csReferer;  CString csDownloadUrl_Old = m_csDownloadUrl;  CString csServer_Old = m_csServer;  CString csObject_Old = m_csObject;  USHORT nPort_Old = m_nPort;  CString csProtocolType_Old = m_csProtocolType;  if ( !ParseResponseString ( csResponse, bRetryRequest ) )  {   if ( !m_csCookieFlag.IsEmpty () )   {    m_csCookieFlag.Empty();    return FALSE;   }   m_csReferer = csReferer_Old;   m_csDownloadUrl = csDownloadUrl_Old;   m_csServer = csServer_Old;   m_csObject = csObject_Old;   m_nPort = nPort_Old;   m_csProtocolType = csProtocolType_Old;   m_csCookieFlag = "Flag=UUIISPoweredByUUSoft";   bRetryRequest = TRUE;  } } if ( pnTailSize )  *pnTailSize = nTailSizeTemp;
 return TRUE;}
//// 获取远程站点信息,如:是否支持断点续传、要下载的文件大小和创建时间等//BOOL CDownloadHttp::GetRemoteSiteInfo_Pro(){ BOOL bRet = FALSE; if ( !CDownloadPub::GetRemoteSiteInfo_Pro() )  goto finished;
 if ( !RequestHttpData ( TRUE ) )  goto finished;
 bRet = TRUE;
finished: return bRet;}
CString CDownloadHttp::GetRequestStr(BOOL bGet){ CString strVerb; if( bGet )  strVerb = _T("GET "); else  strVerb = _T("HEAD ");  CString csReq, strAuth, strRange; csReq  = strVerb  + m_csObject + " HTTP/1.1\r\n";
 if ( !m_csUsername.IsEmpty () ) {  strAuth = _T("");  Base64Encode ( m_csUsername + ":" + m_csPassword, strAuth );  csReq += "Authorization: Basic " + strAuth + "\r\n"; }  CString csPort; if ( m_nPort != DEFAULT_HTTP_PORT )  csPort.Format ( ":%d", m_nPort ); csReq += "Host: " + m_csServer + csPort + "\r\n"; csReq += "Accept: */*\r\n"; csReq += "Pragma: no-cache\r\n";  csReq += "Cache-Control: no-cache\r\n"; csReq += "User-Agent: "+m_csUserAgent+"\r\n"; if( m_csReferer.IsEmpty() ) {  m_csReferer = GetRefererFromURL (); } csReq += "Referer: "+m_csReferer+"\r\n"; csReq += "Connection: close\r\n"; if ( !m_csCookieFlag.IsEmpty() ) {  csReq += "Cookie: " + m_csCookieFlag + "\r\n"; }  // 指定要下载的文件范围 CString csEndPos; int nWillDownloadStartPos = Get_WillDownloadStartPos (); // 开始位置 int nWillDownloadSize = Get_WillDownloadSize();    // 本次应该下载的字节数 int nDownloadedSize = Get_DownloadedSize ();    // 已下载字节数 if ( nWillDownloadSize > 0 )  csEndPos.Format ( "%d", nWillDownloadStartPos+nWillDownloadSize-1 ); ASSERT ( nWillDownloadSize < 0 || nDownloadedSize < nWillDownloadSize ); strRange.Format ( _T("Range: bytes=%d-%s\r\n"), nWillDownloadStartPos+nDownloadedSize, csEndPos );
 csReq += strRange; csReq += "\r\n";  return csReq;}
//// 向服务器提交请求,并得到返回字符串//BOOL CDownloadHttp::SendRequest(LPCTSTR lpszReq, CString &csResponse, char *szTailData/*=NULL*/, int *pnTailSize/*=NULL*/ ){ m_SocketClient.Disconnect (); if ( !Connect () ) return FALSE; if ( !m_SocketClient.SendString ( lpszReq ) ) {  return FALSE; }
 for ( int i=0; ; i++ ) {  char szRecvBuf[NET_BUFFER_SIZE] = {0};  int nReadSize = m_SocketClient.Receive ( szRecvBuf, sizeof(szRecvBuf) );  if ( nReadSize <= 0 )  {   Log ( L_WARNING, "(%d) Receive response data failed", m_nIndex );   return FALSE;  }  csResponse += szRecvBuf;  char *p = strstr ( szRecvBuf, "\r\n\r\n" );  if ( p )  {   if ( szTailData && pnTailSize && *pnTailSize > 0 )   {    p += 4;    int nOtioseSize = nReadSize - int( p - szRecvBuf );    *pnTailSize = MIN ( nOtioseSize, *pnTailSize );    memcpy ( szTailData, p, *pnTailSize );   }#ifdef _DEBUG   int nPos = csResponse.Find ( "\r\n\r\n", 0 );   CString csDump;   if ( nPos >= 0 ) csDump = csResponse.Left ( nPos );   else csDump = csResponse;   Log ( L_NORMAL, "(%d) HTTP server response : \r\n<<<++++++++++++++++++++++++\r\n%s\r\n<<<++++++++++++++++++++++++",    m_nIndex, csDump );#endif   break;  } }
 return TRUE;}
DWORD CDownloadHttp::GetResponseCode(CString csLineText){ csLineText.MakeLower (); ASSERT ( csLineText.Find ( "http/", 0 ) >= 0 ); int nPos = csLineText.Find ( " ", 0 ); if ( nPos < 0 ) return 0; CString csCode = csLineText.Mid ( nPos + 1 ); csCode.TrimLeft(); csCode.TrimRight(); nPos = csCode.Find ( " ", 0 ); if ( nPos < 0 ) nPos = csCode.GetLength() - 1; csCode = csCode.Left ( nPos );
 return (DWORD)atoi(csCode);}
BOOL CDownloadHttp::ParseResponseString ( CString csResponseString, OUT BOOL &bRetryRequest ){ bRetryRequest = FALSE; // 获取返回代码 CString csOneLine = GetOneLine ( csResponseString ); DWORD dwResponseCode = GetResponseCode ( csOneLine ); if ( dwResponseCode < 1 ) {  Log ( L_WARNING, "(%d) Received error response code : %s", m_nIndex, csOneLine );  return FALSE; }  int nPos = 0; // 请求文件被重定向 if( dwResponseCode >= 300 && dwResponseCode < 400 ) {  bRetryRequest = TRUE;  // 得到请求文件新的URL  CString csRedirectFileName = FindAfterFlagString ( "location:", csResponseString );    // 设置 Referer  m_csReferer = GetRefererFromURL ();    // 重定向到其他的服务器  nPos = csRedirectFileName.Find("://");  if ( nPos >= 0 )  {   m_csDownloadUrl = csRedirectFileName;   // 检验要下载的URL是否有效   if ( !ParseURL ( m_csDownloadUrl, m_csServer, m_csObject, m_nPort, m_csProtocolType ) )   {    Log ( L_WARNING, "(%d) Redirect media path [%s] invalid", m_nIndex, m_csDownloadUrl );    return FALSE;   }   return TRUE;  }    // 重定向到本服务器的其他地方  csRedirectFileName.Replace ( "\\", "/" );  // 重定向于根目录  if( csRedirectFileName[0] == '/' )  {   m_csObject = csRedirectFileName;   DownloadNotify ( -1, NOTIFY_TYPE_GOT_REMOTE_FILENAME, (LPVOID)(LPCTSTR)(GetDownloadObjectFileName()), m_pDownloadMTR );   return TRUE;  }    // 定向于相对当前目录  int nParentDirCount = 0;  nPos = csRedirectFileName.Find ( "../" );  while ( nPos >= 0 )  {   csRedirectFileName = csRedirectFileName.Mid(nPos+3);   nParentDirCount++;   nPos = csRedirectFileName.Find("../");  }  for (int i=0; i<=nParentDirCount; i++)  {   nPos = m_csDownloadUrl.ReverseFind('/');   if (nPos != -1)    m_csDownloadUrl = m_csDownloadUrl.Left(nPos);  }  if ( csRedirectFileName.Find ( "./", 0 ) == 0 )   csRedirectFileName.Delete ( 0, 2 );  m_csDownloadUrl = m_csDownloadUrl+"/"+csRedirectFileName;    return ParseURL ( m_csDownloadUrl, m_csServer, m_csObject, m_nPort, m_csProtocolType ); } // 请求被成功接收、理解和接受 else if( dwResponseCode >= 200 && dwResponseCode < 300 ) {  if ( m_nIndex == -1 ) // 主线程才需要获取文件大小的信息  {   // 获取 Content-Length   CString csDownFileLen = FindAfterFlagString ( "content-length:", csResponseString );   m_nFileTotalSize = (int) _ttoi( (LPCTSTR)csDownFileLen );   DownloadNotify ( -1, NOTIFY_TYPE_GOT_REMOTE_FILESIZE, (LPVOID)m_nFileTotalSize, m_pDownloadMTR );   int nWillDownloadStartPos = Get_WillDownloadStartPos (); // 开始位置   int nWillDownloadSize = Get_WillDownloadSize();    // 本次应该下载的字节数   int nDownloadedSize = Get_DownloadedSize ();    // 已下载字节数   if ( m_nFileTotalSize > 0 && nWillDownloadSize-nDownloadedSize > m_nFileTotalSize )    Set_WillDownloadSize ( m_nFileTotalSize-nDownloadedSize );  }    // 获取服务器文件的最后修改时间  CString csModifiedTime = FindAfterFlagString ( "last-modified:", csResponseString );  if ( !csModifiedTime.IsEmpty() )  {   m_TimeLastModified = ConvertHttpTimeString(csModifiedTime);  }
  if ( dwResponseCode == 206 ) // 支持断点续传  {   m_bSupportResume = TRUE;  }  else       // 不支持断点续传  {   m_bSupportResume = FALSE;  }  return TRUE; }
// Log ( L_WARNING, "(%d) Receive invalid code : %d", m_nIndex, dwResponseCode ); return FALSE;}
CString CDownloadHttp::FindAfterFlagString(LPCTSTR lpszFoundStr, CString csOrg){ ASSERT ( lpszFoundStr && strlen(lpszFoundStr) > 0 ); CString csReturing, csFoundStr = GET_SAFE_STRING(lpszFoundStr); csFoundStr.MakeLower (); CString csOrgLower = csOrg; csOrgLower.MakeLower (); int nPos = csOrgLower.Find ( csFoundStr ); if ( nPos < 0 ) return ""; csReturing = csOrg.Mid ( nPos + csFoundStr.GetLength() ); nPos = csReturing.Find("\r\n"); if ( nPos < 0 ) return ""; csReturing = csReturing.Left(nPos); csReturing.TrimLeft(); csReturing.TrimRight();
 return csReturing;}
//// 将 HTTP 服务器表示的时间转换为 CTime 格式,如:Wed, 16 May 2007 14:29:53 GMT//CTime CDownloadHttp::ConvertHttpTimeString(CString csTimeGMT){ CString csYear, csMonth, csDay, csTime; CTime tReturning = -1; int nPos = csTimeGMT.Find ( ",", 0 ); if ( nPos < 0 || nPos >= csTimeGMT.GetLength()-1 )  return tReturning; csTimeGMT = csTimeGMT.Mid ( nPos + 1 ); csTimeGMT.TrimLeft(); csTimeGMT.TrimRight ();
 // 日 nPos = csTimeGMT.Find ( " ", 0 ); if ( nPos < 0 || nPos >= csTimeGMT.GetLength()-1 )  return tReturning; csDay = csTimeGMT.Left ( nPos ); csTimeGMT = csTimeGMT.Mid ( nPos + 1 ); csTimeGMT.TrimLeft(); csTimeGMT.TrimRight ();
 // 月 nPos = csTimeGMT.Find ( " ", 0 ); if ( nPos < 0 || nPos >= csTimeGMT.GetLength()-1 )  return tReturning; csMonth = csTimeGMT.Left ( nPos ); int nMonth = GetMouthByShortStr ( csMonth ); ASSERT ( nMonth >= 1 && nMonth <= 12 ); csMonth.Format ( "%02d", nMonth ); csTimeGMT = csTimeGMT.Mid ( nPos + 1 ); csTimeGMT.TrimLeft(); csTimeGMT.TrimRight ();
 // 年 nPos = csTimeGMT.Find ( " ", 0 ); if ( nPos < 0 || nPos >= csTimeGMT.GetLength()-1 )  return tReturning; csYear = csTimeGMT.Left ( nPos ); csTimeGMT = csTimeGMT.Mid ( nPos + 1 ); csTimeGMT.TrimLeft(); csTimeGMT.TrimRight ();
 // 时间 nPos = csTimeGMT.Find ( " ", 0 ); if ( nPos < 0 || nPos >= csTimeGMT.GetLength()-1 )  return tReturning; csTime = csTimeGMT.Left ( nPos ); csTimeGMT = csTimeGMT.Mid ( nPos + 1 );
 CString csFileTimeInfo; csFileTimeInfo.Format ( "%s-%s-%s %s", csYear, csMonth, csDay, csTime ); ConvertStrToCTime ( csFileTimeInfo.GetBuffer(0), tReturning ); return tReturning;}
智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告