?? downloadpub.cpp
字號:
// DownloadPub.cpp: implementation of the CDownloadPub class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "NetDownMTR.h"
#include "DownloadPub.h"
// for PathFindExtension () / PathFindFileName ()
#include "Shlwapi.h"
#pragma comment ( lib, "shlwapi.lib" )
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
// 下載數據保存的臨時緩沖大小
#define TEMP_SAVE_BUFFER_SIZE (10*NET_BUFFER_SIZE)
// 當下載的數據達到這個數的時候才保存到文件中
#define WRITE_TEMP_SAVE_MIN_BYTES (TEMP_SAVE_BUFFER_SIZE / 2)
void DownloadNotify ( int nIndex, UINT nNotityType, LPVOID lpNotifyData, LPVOID pDownloadMTR );
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDownloadPub::CDownloadPub()
{
m_hThread = NULL;
m_TimeLastModified = -1;
m_csDownloadUrl = _T("");
m_csSaveFileName = _T("");
m_Proc_SaveDownloadInfo = NULL;
m_wSaveDownloadInfo_Param = NULL;
m_bSupportResume = FALSE;
m_nFileTotalSize = -1;
m_csReferer = _T("");
m_csUserAgent = _T("XieHongWei-HttpDown/2.0");
m_csUsername = _T("");
m_csPassword = _T("");
m_csProtocolType = "http";
m_csServer = _T("");
m_csObject = _T("");
m_csFileName = _T("");
m_nPort = DEFAULT_HTTP_PORT ;
m_nIndex = -1;
ResetVar ();
m_hEvtEndModule = ::CreateEvent ( NULL, TRUE, FALSE, NULL );
m_pDownloadMTR = NULL;
}
void CDownloadPub::ResetVar()
{
Clear_Thread_Handle ();
m_nWillDownloadStartPos = 0;
m_nWillDownloadSize = -1;
m_nDownloadedSize = 0;
m_nTempSaveBytes = 0;
m_bDownloadSuccess = FALSE;
}
CDownloadPub::~CDownloadPub()
{
StopDownload ();
Clear_Thread_Handle ();
}
void CDownloadPub::StopDownload ()
{
if ( HANDLE_IS_VALID(m_hEvtEndModule) )
{
::SetEvent ( m_hEvtEndModule );
WaitForThreadEnd ( m_hThread,30*1000 );
CLOSE_HANDLE ( m_hEvtEndModule );
m_hEvtEndModule = NULL;
Clear_Thread_Handle ();
}
}
//
// 設置認證信息
//
void CDownloadPub::SetAuthorization ( LPCTSTR lpszUsername, LPCTSTR lpszPassword )
{
if( lpszUsername != NULL )
{
m_csUsername = GET_SAFE_STRING(lpszUsername);
m_csPassword = GET_SAFE_STRING(lpszPassword);
}
else
{
m_csUsername = _T("");
m_csPassword = _T("");
}
}
// 設置Referer
void CDownloadPub::SetReferer(LPCTSTR lpszReferer)
{
if( lpszReferer != NULL )
m_csReferer = lpszReferer;
else
m_csReferer = _T("");
}
// 設置UserAgent
void CDownloadPub::SetUserAgent(LPCTSTR lpszUserAgent)
{
m_csUserAgent = lpszUserAgent;
if( m_csUserAgent.IsEmpty())
m_csUserAgent = _T("XieHongWei-HttpDown/2.0");
}
//
// 設置保存下載信息回調函數
//
void CDownloadPub::Set_SaveDownloadInfo_Callback ( FUNC_SaveDownloadInfo Proc_SaveDownloadInfo, WPARAM wParam )
{
m_Proc_SaveDownloadInfo = Proc_SaveDownloadInfo;
m_wSaveDownloadInfo_Param = wParam;
}
//
// 下載任務的線程函數
//
DWORD WINAPI ThreadProc_Download(
LPVOID lpParameter // thread data
)
{
CDownloadPub *pDownloadPub = (CDownloadPub*)lpParameter;
ASSERT ( pDownloadPub );
return pDownloadPub->ThreadProc_Download ();
}
BOOL CDownloadPub::ThreadProc_Download()
{
for ( int i=0; i<RETRY_TIMES; i++ )
{
if ( DownloadOnce () )
return DownloadEnd(TRUE);
SLEEP_RETURN_Down ( 5*1000 );
}
return DownloadEnd(FALSE);
}
BOOL CDownloadPub::DownloadOnce()
{
// 打開文件
if ( !OpenFileForSave () )
return FALSE;
// 連接到服務器
if ( !m_SocketClient.Is_Connected () )
{
if ( !Connect () )
return FALSE;
}
return TRUE;
}
//
// 創建線程下載文件
//
BOOL CDownloadPub::Download (
int nWillDownloadStartPos, // 要下載文件的開始位置
int nWillDownloadSize, // 本次需要下載的大小,-1表示一直下載到文件尾
int nDownloadedSize // 已下載的字節數,指完全寫到文件中的字節數
)
{
// 設置下載參數
m_nWillDownloadStartPos = nWillDownloadStartPos;
Set_WillDownloadSize ( nWillDownloadSize );
if ( m_nFileTotalSize > 0 && Get_WillDownloadSize() > m_nFileTotalSize )
{
Set_WillDownloadSize ( m_nFileTotalSize );
}
Set_DownloadedSize ( nDownloadedSize );
// 創建一個下載線程
DWORD dwThreadId = 0;
m_hThread = CreateThread ( NULL, 0, ::ThreadProc_Download, LPVOID(this), 0, &dwThreadId );
if ( !HANDLE_IS_VALID(m_hThread) )
{
Log ( L_WARNING, "Create download thread failed" );
return FALSE;
}
return TRUE;
}
//
// 下載結束
//
BOOL CDownloadPub::DownloadEnd(BOOL bRes)
{
m_bDownloadSuccess = bRes;
m_SocketClient.Disconnect ();
if ( HANDLE_IS_VALID ( m_file.m_hFile ) )
{
m_file.Close ();
}
TRACE ( "=============== 線程。%d 下載 %s 結束\n", m_nIndex, bRes?"成功":"!!! 失敗 !!!" );
return bRes;
}
BOOL CDownloadPub::Connect()
{
if ( !HANDLE_IS_VALID(m_hEvtEndModule) )
return FALSE;
if ( m_csServer.IsEmpty() )
{
Log ( L_WARNING, "Please set download URL" );
return FALSE;
}
m_SocketClient.SetEventOfEndModule ( m_hEvtEndModule );
// 連接到服務器
if ( !m_SocketClient.Connect ( m_csServer, m_nPort ) )
return FALSE;
TRACE ( "對象.%d 連接到服務器 成功\n", m_nIndex );
return TRUE;
}
BOOL CDownloadPub::SetDownloadUrl(LPCTSTR lpszDownloadUrl)
{
if ( !lpszDownloadUrl ) return FALSE;
m_csDownloadUrl = lpszDownloadUrl;
// 檢驗要下載的URL是否為空
m_csDownloadUrl.TrimLeft();
m_csDownloadUrl.TrimRight();
if( m_csDownloadUrl.IsEmpty() )
return FALSE;
// 檢驗要下載的URL是否有效
if ( !ParseURL(m_csDownloadUrl, m_csServer, m_csObject, m_nPort, m_csProtocolType))
{
TRACE(_T("Failed to parse the URL: %s\n"), m_csDownloadUrl);
return FALSE;
}
return TRUE;
}
//
// 從服務器接收數據并保存到文件中
//
BOOL CDownloadPub::RecvDataAndSaveToFile(CSocketClient &SocketClient,char *szTailData/*=NULL*/, int nTailSize/*=0*/)
{
int nDownloadedSize = Get_DownloadedSize();
if ( szTailData && nTailSize > 0 )
{
nDownloadedSize = SaveDataToFile ( szTailData, nTailSize );
if ( nDownloadedSize < 0 )
{
return FALSE;
}
}
char szRecvBuf[NET_BUFFER_SIZE] = {0}, *szTempSaveBuf = new char[TEMP_SAVE_BUFFER_SIZE];
if ( !szTempSaveBuf )
{
Log ( L_ERROR, "Allocate memory failed" );
return FALSE;
}
m_nTempSaveBytes = 0;
while ( TRUE )
{
BOOL bDownloadFinished = FALSE;
int nReadSize = 0;
int nTempSaveBytes = Get_TempSaveBytes ();
int nRecvTotalBytes = nDownloadedSize+nTempSaveBytes; // 保存在文件中的字節數加上臨時緩沖中的字節數就是總共接收到字節數
int nWillDownloadSize = Get_WillDownloadSize ();
// 從字節數判斷,本次下載已經完成了
if ( nWillDownloadSize > 0 && nRecvTotalBytes >= nWillDownloadSize )
{
bDownloadFinished = TRUE;
}
else
{
int nRecvBytesThisTimes = sizeof(szRecvBuf);
if ( nWillDownloadSize > 0 )
nRecvBytesThisTimes = nWillDownloadSize - nRecvTotalBytes;
ASSERT ( nRecvBytesThisTimes >= 0 );
nRecvBytesThisTimes = MIN ( nRecvBytesThisTimes, sizeof(szRecvBuf) );
nReadSize = SocketClient.Receive ( szRecvBuf, nRecvBytesThisTimes );
// 讀不到數據了,所以認為下載已經完成
if ( nReadSize <= 0 )
{
if ( nWillDownloadSize <= 0 )
{
bDownloadFinished = TRUE;
}
}
else
{
// TRACE ( "對象.%d, 收到 %d 字節,我的任務是 %d (0x%08x)字節\n",
// m_nIndex, nReadSize, nWillDownloadSize , nWillDownloadSize );
}
}
// 先將數據保存到臨時緩沖中
if ( nReadSize > 0 )
{
nReadSize = MIN ( nReadSize, TEMP_SAVE_BUFFER_SIZE-nTempSaveBytes );
memcpy ( szTempSaveBuf+nTempSaveBytes, szRecvBuf, nReadSize );
nTempSaveBytes += nReadSize;
ASSERT ( nTempSaveBytes < TEMP_SAVE_BUFFER_SIZE );
}
// 當下載已完成或者收到的數據超過一定數量時才保存到文件中
if ( bDownloadFinished || nTempSaveBytes >= WRITE_TEMP_SAVE_MIN_BYTES )
{
// 保存文件失敗,下載也應該終止
nDownloadedSize = SaveDataToFile ( szTempSaveBuf, nTempSaveBytes );
if ( nDownloadedSize < 0 )
{
break;
}
nTempSaveBytes = 0;
}
Set_TempSaveBytes ( nTempSaveBytes );
if ( bDownloadFinished )
{
ASSERT ( (nWillDownloadSize > 0 && nDownloadedSize >= nWillDownloadSize) || (nReadSize <= 0 && nWillDownloadSize <= 0) );
break;
}
SLEEP_BREAK ( 1 );
}
if ( szTempSaveBuf ) delete[] szTempSaveBuf;
szTempSaveBuf = NULL;
BOOL bRes = FALSE;
int nWillDownloadSize = Get_WillDownloadSize ();
if ( nWillDownloadSize != -1 )
{
if ( nDownloadedSize >= nWillDownloadSize )
bRes = TRUE;
}
else if ( nDownloadedSize > 0 )
{
bRes = TRUE;
}
return bRes;
}
int CDownloadPub::SaveDataToFile(char *data, int size)
{
ASSERT ( HANDLE_IS_VALID ( m_file.m_hFile ) );
if ( !data || size < 0 )
return -1;
int nDownloadedSize = -1;
// 保存下載的數據
ASSERT ( HANDLE_IS_VALID(m_file.m_hFile) );
BOOL bRet = TRUE;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -