MFC 下载网络文件到本地 利用 CHttpFile 和 URLDownloadToFile 【可设超时及进度】两种方式

24 篇文章 1 订阅

说明

方法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

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值