说明
方法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;
}
}
CCallback 类下载地址:https://download.csdn.net/download/qiangzi4646/10474541