MFC 下載網路檔案到本地 利用 CHttpFile 和 URLDownloadToFile 【可設超時及進度】兩種方式
阿新 • • 發佈:2019-01-30
說明
方法1較為簡單,通用的多,但在某些環境下可能出現未知錯誤(也有可能你碰不到,反正我是碰到了)。
方法2實現相對麻煩點,但可設定超時時間以及進度展示,但要例項化一個LPBINDSTATUSCALLBACK 子類,在這個子類中去實現。這個相對好用點,方法1遇到的錯誤的情況,用方法2卻可以正常使用。
LPBINDSTATUSCALLBACK 這個子類程式碼沒有貼出來,放在文未,可點選下載。
方法1 利用CHttpFile下載
函式如下:
void CHttpData::DownloadFile(CString strURL,CString strLocalPath)
{
const int dwBufSize = 1024;
CInternetSession* Session = new CInternetSession;
CHttpFile* pHttpFile = NULL;
CStdioFile pLocalFile;
DWORD dwlen;
LoggerCio::notice(LoggerCio::LOG_SYS,"*** CHttpData::DownloadFile");
LPBYTE lpBuf = new byte[dwBufSize];
if(FALSE == pLocalFile.Open(strLocalPath, CFile::modeCreate | CFile::modeWrite | CFile::typeBinary))
{
LoggerCio::notice(LoggerCio::LOG_SYS,"*** 下載檔案到本地失敗,沒有本地寫許可權" );
return;
}
//判斷檔案是否存在
HANDLE hFind;
WIN32_FIND_DATA wfd;
hFind=FindFirstFile(strLocalPath,&wfd);
if(hFind != INVALID_HANDLE_VALUE){
//存在則刪除
DeleteFile(strLocalPath);
LoggerCio::notice(LoggerCio::LOG_SYS,"delete the existing");
}
FindClose(hFind);
// 增加OpenURL保護
HINTERNET hOpen = InternetOpen (NULL,PRE_CONFIG_INTERNET_ACCESS,NULL, NULL, 0);
HINTERNET hRequest = InternetOpenUrl (hOpen, strURL,NULL, 0, INTERNET_FLAG_TRANSFER_BINARY,0);
if(!hRequest ){
delete[] lpBuf;
lpBuf = NULL;
LoggerCio::notice(LoggerCio::LOG_SYS,"*** 開啟strURL失敗");
return;
}
if( hOpen )
InternetCloseHandle(hOpen );
if(hRequest )
InternetCloseHandle(hRequest );
pHttpFile = (CHttpFile*)Session->OpenURL(
strURL,
1,
INTERNET_FLAG_TRANSFER_BINARY |
INTERNET_FLAG_RELOAD |
INTERNET_FLAG_DONT_CACHE,
NULL,
0);
if (NULL == pHttpFile)
{
delete[] lpBuf;
lpBuf = NULL;
LoggerCio::notice(LoggerCio::LOG_SYS,"*** CHttpData::OpenURL返回值為空");
return;
}
DWORD dwStatusCode;
pHttpFile->QueryInfoStatusCode(dwStatusCode);
if (HTTP_STATUS_OK == dwStatusCode)
{
LoggerCio::notice(LoggerCio::LOG_SYS,"open url finish and HTTP_STATUS_OK");
while(dwlen = pHttpFile-> Read(lpBuf, dwBufSize-1 ))
{
pLocalFile.Write(lpBuf,dwlen);
}
LoggerCio::notice(LoggerCio::LOG_SYS,"*** file download finish");
pHttpFile->Close();//關閉CHttpFile 並釋放其資源。只有在對SendRequest的成功呼叫或者一個CHttpFile物件被 OpenURL成功建立後,才能使用該成員函式。
pHttpFile=NULL;
}
//資源回收
Session->Close();
pLocalFile.Close();
delete[] lpBuf;
lpBuf = NULL;
}
方法2 URLDownloadToFile (可設超時時間,顯示進度)
//strURL:網路地址,strLocalPath:要儲存的本地地址,nTimeOutSec:超時秒數
BOOL CHttpData::downloadFileByIe3(CString strURL,CString strLocalPath,int nTimeOutSec)
{
CCallback callback;//派生自IBindStatusCallback的子類
// If the user wants a timeout, calculate the time when the download
// should abort.
if ( nTimeOutSec > 0 )
{
callback.m_bUseTimeout = TRUE;
callback.m_timeToStop = CTime::GetCurrentTime() + CTimeSpan( 0, 0, 0, nTimeOutSec );
}
HRESULT hr;
hr = URLDownloadToFile ( NULL, // ptr to ActiveX container
strURL, // URL to get
strLocalPath, // file to store data in
0, // reserved
&callback // ptr to IBindStatusCallback
);
if ( SUCCEEDED(hr) )
return TRUE;
else
{
LPTSTR lpszErrorMessage;
CString sMsg;
if ( FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, hr,
MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ),
(LPTSTR) &lpszErrorMessage, 0, NULL ))
{
sMsg.Format ( _T("Download failed. Error = 0x%08lX\n\n%s"),
(DWORD) hr, lpszErrorMessage );
LocalFree ( lpszErrorMessage );
}
else
{
sMsg.Format ( _T("Download failed. Error = 0x%08lX\n\nNo message available."),
(DWORD) hr );
}
OutputDebugStringW(sMsg);
USES_CONVERSION;
LoggerCio::notice(LoggerCio::LOG_SYS,"%s",T2A(sMsg));
return FALSE;
}
}