📄 httpdownload.cpp
字号:
m_nRetryDelay = nRetryDelay;
m_nRetryMax = nRetryMax;
// 检查一下m_nRetryMax,如果为0,设为缺省值
if( (RETRY_TYPE_TIMES == m_nRetryType) && (0 == m_nRetryMax) )
m_nRetryMax = DEFAULT_RETRY_MAX;
}
// 获取下载文件的状态
BOOL CHttpDownload::GetDownloadFileStatus(LPCTSTR lpszDownloadUrl, DWORD &dwFileSize, CTime &FileTime)
{
// 检验要下载的URL是否为空
m_strDownloadUrl = lpszDownloadUrl;
m_strDownloadUrl.TrimLeft();
m_strDownloadUrl.TrimRight();
if( m_strDownloadUrl.IsEmpty() )
return FALSE;
// 检验要下载的URL是否有效
if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
{
// 在前面加上"http://"再试
m_strDownloadUrl = _T("http://") + m_strDownloadUrl;
if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort) )
{
TRACE(_T("Failed to parse the URL: %s\n"), m_strDownloadUrl);
return FALSE;
}
}
m_strTempSavePath = "|";
m_bStopDownload = FALSE;
if ( SendRequest(TRUE) != SENDREQUEST_SUCCESS )
return FALSE;
dwFileSize = m_dwDownloadSize;
FileTime = m_TimeLastModified;
return TRUE;
}
// 从URL里面拆分出Server和Object来
BOOL CHttpDownload::ParseURL(LPCTSTR lpszURL, CString &strServer, CString &strObject,USHORT& nPort)
{
CString strURL(lpszURL);
strURL.TrimLeft();
strURL.TrimRight();
// 清除数据
strServer = _T("");
strObject = _T("");
nPort = 0;
int nPos = strURL.Find("://");
if( nPos == -1 )
return FALSE;
// 进一步验证是否为http://
CString strTemp = strURL.Left( nPos+lstrlen("://") );
strTemp.MakeLower();
if( strTemp.Compare("http://") != 0 )
return FALSE;
strURL = strURL.Mid( strTemp.GetLength() );
nPos = strURL.Find('/');
if ( nPos == -1 )
return FALSE;
strObject = strURL.Mid(nPos);
strTemp = strURL.Left(nPos);
///////////////////////////////////////////////////////////////
/// 注意:并没有考虑URL中有用户名和口令的情形和最后有#的情形
/// 例如:http://abc@def:www.yahoo.com:81/index.html#link1
///
//////////////////////////////////////////////////////////////
// 查找是否有端口号
nPos = strTemp.Find(":");
if( nPos == -1 )
{
strServer = strTemp;
nPort = DEFAULT_HTTP_PORT;
}
else
{
strServer = strTemp.Left( nPos );
strTemp = strTemp.Mid( nPos+1 );
nPort = (USHORT)_ttoi((LPCTSTR)strTemp);
}
return TRUE;
}
// 从返回到头里获得必要的信息
UINT CHttpDownload::GetInfo(LPCTSTR lpszHeader, DWORD &dwContentLength, DWORD &dwStatusCode, CTime &TimeLastModified)
{
dwContentLength = 0;
dwStatusCode = 0;
TimeLastModified= CTime::GetCurrentTime();
CString strHeader = lpszHeader;
strHeader.MakeLower();
//拆分出HTTP应答的头信息的第一行
int nPos = strHeader.Find("\r\n");
if (nPos == -1)
return HTTP_FAIL;
CString strFirstLine = strHeader.Left(nPos);
// 获得返回码: Status Code
strFirstLine.TrimLeft();
strFirstLine.TrimRight();
nPos = strFirstLine.Find(' ');
if( nPos == -1 )
return HTTP_FAIL;
strFirstLine = strFirstLine.Mid(nPos+1);
nPos = strFirstLine.Find(' ');
if( nPos == -1 )
return HTTP_FAIL;
strFirstLine = strFirstLine.Left(nPos);
dwStatusCode = (DWORD)_ttoi((LPCTSTR)strFirstLine);
// 检查返回码
if( dwStatusCode >= 300 && dwStatusCode < 400 ) //首先检测一下服务器的应答是否为重定向
{
nPos = strHeader.Find("location:");
if (nPos == -1)
return HTTP_FAIL;
CString strRedirectFileName = strHeader.Mid(nPos + strlen("location:"));
nPos = strRedirectFileName.Find("\r\n");
if (nPos == -1)
return HTTP_FAIL;
strRedirectFileName = strRedirectFileName.Left(nPos);
strRedirectFileName.TrimLeft();
strRedirectFileName.TrimRight();
// 设置Referer
m_strReferer = m_strDownloadUrl;
// 判断是否重定向到其他的服务器
nPos = strRedirectFileName.Find("http://");
if( nPos != -1 )
{
m_strDownloadUrl = strRedirectFileName;
// 检验要下载的URL是否有效
if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
return HTTP_FAIL;
return HTTP_REDIRECT;
}
// 重定向到本服务器的其他地方
strRedirectFileName.Replace("\\","/");
// 是相对于根目录
if( strRedirectFileName[0] == '/' )
{
m_strObject = strRedirectFileName;
return HTTP_REDIRECT;
}
// 是相对当前目录
int nParentDirCount = 0;
nPos = strRedirectFileName.Find("../");
while (nPos != -1)
{
strRedirectFileName = strRedirectFileName.Mid(nPos+3);
nParentDirCount++;
nPos = strRedirectFileName.Find("../");
}
for (int i=0; i<=nParentDirCount; i++)
{
nPos = m_strDownloadUrl.ReverseFind('/');
if (nPos != -1)
m_strDownloadUrl = m_strDownloadUrl.Left(nPos);
}
m_strDownloadUrl = m_strDownloadUrl+"/"+strRedirectFileName;
if ( !ParseURL(m_strDownloadUrl, m_strServer, m_strObject, m_nPort))
return HTTP_FAIL;
return HTTP_REDIRECT;
}
// 服务器错误,可以重试
if( dwStatusCode >=500 )
return HTTP_ERROR;
// 客户端错误,重试无用
if( dwStatusCode >=400 && dwStatusCode <500 )
return HTTP_FAIL;
// 获取ContentLength
nPos = strHeader.Find("content-length:");
if (nPos == -1)
return HTTP_FAIL;
CString strDownFileLen = strHeader.Mid(nPos + strlen("content-length:"));
nPos = strDownFileLen.Find("\r\n");
if (nPos == -1)
return HTTP_FAIL;
strDownFileLen = strDownFileLen.Left(nPos);
strDownFileLen.TrimLeft();
strDownFileLen.TrimRight();
// Content-Length:
dwContentLength = (DWORD) _ttoi( (LPCTSTR)strDownFileLen );
// 获取Last-Modified:
nPos = strHeader.Find("last-modified:");
if (nPos != -1)
{
CString strTime = strHeader.Mid(nPos + strlen("last-modified:"));
nPos = strTime.Find("\r\n");
if (nPos != -1)
{
strTime = strTime.Left(nPos);
strTime.TrimLeft();
strTime.TrimRight();
TimeLastModified = GetTime(strTime);
}
}
return HTTP_OK;
}
// 将字符串转化成时间
CTime CHttpDownload::GetTime(LPCTSTR lpszTime)
{
int nDay,nMonth,nYear,nHour,nMinute,nSecond;
CString strTime = lpszTime;
int nPos = strTime.Find(',');
if (nPos != -1)
{
strTime = strTime.Mid(nPos+1);
strTime.TrimLeft();
CString strDay,strMonth,strYear,strHour,strMinute,strSecond;
CString strAllMonth = "jan,feb,mar,apr,may,jan,jul,aug,sep,oct,nov,dec";
strDay = strTime.Left(2);
nDay = atoi(strDay);
strMonth = strTime.Mid(3,3);
strMonth.MakeLower();
nPos = strAllMonth.Find(strMonth);
if (nPos != -1)
{
strMonth.Format("%d",((nPos/4)+1));
nMonth = atoi(strMonth);
}
else
nMonth = 1;
strTime = strTime.Mid(6);
strTime.TrimLeft();
nPos = strTime.FindOneOf(" \t");
if (nPos != -1)
{
strYear = strTime.Left(nPos);
nYear = atoi(strYear);
}
else
nYear = 2000;
strTime = strTime.Mid(nPos+1);
strHour = strTime.Left(2);
nHour = atoi(strHour);
strMinute = strTime.Mid(3,2);
nMinute = atoi(strMinute);
strSecond = strTime.Mid(6,2);
nSecond = atoi(strSecond);
}
CTime time(nYear,nMonth,nDay,nHour,nMinute,nSecond);
return time;
}
// 停止下载
void CHttpDownload::StopDownload()
{
m_bStopDownload = TRUE;
}
// STATIC BASE64解码
int CHttpDownload::Base64Decode(LPCTSTR lpszDecoding, CString &strDecoded)
{
int nIndex =0;
int nDigit;
int nDecode[ 256 ];
int nSize;
int nNumBits = 6;
if( lpszDecoding == NULL )
return 0;
if( ( nSize = lstrlen(lpszDecoding) ) == 0 )
return 0;
// Build Decode Table
for( int i = 0; i < 256; i++ )
nDecode[i] = -2; // Illegal digit
for( i=0; i < 64; i++ )
{
nDecode[ m_strBase64TAB[ i ] ] = i;
nDecode[ '=' ] = -1;
}
// Clear the output buffer
strDecoded = _T("");
long lBitsStorage =0;
int nBitsRemaining = 0;
int nScratch = 0;
UCHAR c;
// Decode the Input
for( nIndex = 0, i = 0; nIndex < nSize; nIndex++ )
{
c = lpszDecoding[ nIndex ];
// 忽略所有不合法的字符
if( c> 0x7F)
continue;
nDigit = nDecode[c];
if( nDigit >= 0 )
{
lBitsStorage = (lBitsStorage << nNumBits) | (nDigit & 0x3F);
nBitsRemaining += nNumBits;
while( nBitsRemaining > 7 )
{
nScratch = lBitsStorage >> (nBitsRemaining - 8);
strDecoded += (nScratch & 0xFF);
i++;
nBitsRemaining -= 8;
}
}
}
return strDecoded.GetLength();
}
// STATIC BASE64编码
int CHttpDownload::Base64Encode(LPCTSTR lpszEncoding, CString &strEncoded)
{
int nDigit;
int nNumBits = 6;
int nIndex = 0;
int nInputSize;
strEncoded = _T( "" );
if( lpszEncoding == NULL )
return 0;
if( ( nInputSize = lstrlen(lpszEncoding) ) == 0 )
return 0;
int nBitsRemaining = 0;
long lBitsStorage =0;
long lScratch =0;
int nBits;
UCHAR c;
while( nNumBits > 0 )
{
while( ( nBitsRemaining < nNumBits ) && ( nIndex < nInputSize ) )
{
c = lpszEncoding[ nIndex++ ];
lBitsStorage <<= 8;
lBitsStorage |= (c & 0xff);
nBitsRemaining += 8;
}
if( nBitsRemaining < nNumBits )
{
lScratch = lBitsStorage << ( nNumBits - nBitsRemaining );
nBits = nBitsRemaining;
nBitsRemaining = 0;
}
else
{
lScratch = lBitsStorage >> ( nBitsRemaining - nNumBits );
nBits = nNumBits;
nBitsRemaining -= nNumBits;
}
nDigit = (int)(lScratch & m_nBase64Mask[nNumBits]);
nNumBits = nBits;
if( nNumBits <=0 )
break;
strEncoded += m_strBase64TAB[ nDigit ];
}
// Pad with '=' as per RFC 1521
while( strEncoded.GetLength() % 4 != 0 )
strEncoded += '=';
return strEncoded.GetLength();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -