⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 controller_downloadfile.h

📁 用VC
💻 H
📖 第 1 页 / 共 2 页
字号:
        else if (msg == GetMsg_Progress())
        {
            WM_DLF_PROGRESS   * p = (WM_DLF_PROGRESS*)wParam ;
            DownloadFile_OnProgress (*p->pstrFileURL, p->nNow, p->nTotal) ;
            return 0 ;
        }
        else if (msg == GetMsg_Error())
        {
            DownloadFile_OnError (*(CString*)wParam) ;
            return 0 ;
        }
        else if (msg == GetMsg_StartDownload())
        {
            DownloadFile_OnStartDownload (*(CString*)wParam) ;
            return 0 ;
        }
        return T::WindowProc(msg, wParam, lParam) ;
    }

private:
    // thread handle <==> download file URL
    PCL_TT_Convertor<HANDLE, CString>   m_ThreadTab ;

    // information pass to thread
    struct PARA_DATA
    {
        FCDownloadFileWndBase   * pThis ;
        CString   strFileURL ;
    };

    // message notify owner window
    static UINT GetMsg_CheckTime()     {return ::RegisterWindowMessage (_T("UISTONE_WM_DOWNFILE_CHECKTIME")); }
    static UINT GetMsg_DownFinished()  {return ::RegisterWindowMessage (_T("UISTONE_WM_DOWNFILE_DOWNFINISHED"));}
    static UINT GetMsg_ProxyValidate() {return ::RegisterWindowMessage (_T("UISTONE_WM_DOWNFILE_PROXYVALIDATE"));}
    static UINT GetMsg_Error()         {return ::RegisterWindowMessage (_T("UISTONE_WM_DOWNFILE_ERROR"));}
    static UINT GetMsg_StartDownload() {return ::RegisterWindowMessage (_T("UISTONE_WM_DOWNFILE_STARTDOWNLOAD"));}
    static UINT GetMsg_Progress()      {return ::RegisterWindowMessage (_T("UISTONE_WM_DOWNFILE_PROGRESS"));}

    // inner notify message struct
    struct WM_DLF_CHECKTIME
    {
        WM_DLF_CHECKTIME (CString* pURL, CString* pT) : pstrFileURL(pURL), pStrTime(pT) {}
        CString   * pstrFileURL ;
        CString   * pStrTime ;
    };
    struct WM_DLF_FINISHED
    {
        WM_DLF_FINISHED (CString* pURL, char* pB, int n) : pstrFileURL(pURL), pBuffer(pB), nLength(n) {}
        CString   * pstrFileURL ;
        char      * pBuffer ;
        int       nLength ;
    };
    struct WM_DLF_PROXY_VALIDATE
    {
        WM_DLF_PROXY_VALIDATE (CString* pURL, CString* pN, CString* pP) : pstrFileURL(pURL), pStrUsername(pN), pStrPassword(pP) {}
        CString   * pstrFileURL ;
        CString   * pStrUsername ;
        CString   * pStrPassword ;
    };
    struct WM_DLF_PROGRESS
    {
        WM_DLF_PROGRESS (CString* pURL, int nN, int nT) : pstrFileURL(pURL), nNow(nN), nTotal(nT) {}
        CString   * pstrFileURL ;
        int       nNow ;
        int       nTotal ;
    };

    LRESULT df_Notify (UINT msg, void* pNotify)
    {
        if (!::IsWindow (GetSafeHwnd()))
            return FALSE ;
        return SendMessage (msg, (WPARAM)pNotify) ;
    }

    struct __FCAutoInitializeCOM
    {
        __FCAutoInitializeCOM()  {CoInitialize(0);}
        ~__FCAutoInitializeCOM() {CoUninitialize();}
    };

    static bstr_t QueryTempFilePath()
    {
        TCHAR   szTmpPath[MAX_PATH],
                szFilename[MAX_PATH] ;
        ::GetTempPath (MAX_PATH, szTmpPath) ;
        ::GetTempFileName (szTmpPath, TEXT("foo"), 0, szFilename) ;
        return szFilename ;
    }

    static void LoadFileToBuffer (const char* szFilename, char*& pBuffer, int& nLength)
    {
        pBuffer=0; nLength=0;
        std::ifstream     inFile (szFilename, std::ios::in|std::ios::binary) ;
        if (!inFile.is_open())
            {assert(false); return;}

        // get file length
        inFile.seekg (0, std::ios::end) ;
        nLength = (int)inFile.tellg() ;
        if (nLength <= 0)
            {assert(false); return;}

        // read file into memory
        pBuffer = new char[nLength + 8] ;
        memset (&pBuffer[nLength], 0, 8) ;
        inFile.seekg (0, std::ios::beg) ;
        inFile.read (pBuffer, nLength) ;
    }

    // encapsuled download thread.
    static DWORD WINAPI __uis_DownloadFile (LPVOID lpParameter)
    {
        __FCAutoInitializeCOM      _aAutoCOM ;
        std::auto_ptr<PARA_DATA>   pPara ((PARA_DATA*)lpParameter) ;

        // start download file
        char   * pBuf = NULL ;
        int    nBufLen = 0 ;
        TRY
        {
            // connection
            CInternetSession   sess ;
            sess.SetOption (INTERNET_OPTION_CONNECT_TIMEOUT, 30 * 1000) ;
            sess.SetOption (INTERNET_OPTION_CONNECT_BACKOFF, 1000) ;
            sess.SetOption (INTERNET_OPTION_CONNECT_RETRIES, 1) ;

            DWORD       dwFlag = INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_DONT_CACHE|INTERNET_FLAG_RELOAD ;
            CHttpFile   * pF = (CHttpFile*)sess.OpenURL(pPara->strFileURL, 1, dwFlag); ASSERT(pF);
            if (!pF)
                {AfxThrowInternetException(1);}

            // connection status
            CString      str ;
            pF->QueryInfo (HTTP_QUERY_STATUS_CODE, str) ;

            // Proxy Authentication Required
            if (str == _T("407"))
            {
                CString   strUsername, strPassword ;
                pPara->pThis->df_Notify (GetMsg_ProxyValidate(), &WM_DLF_PROXY_VALIDATE(&pPara->strFileURL, &strUsername, &strPassword)) ;
                pF->SetOption (INTERNET_OPTION_PROXY_USERNAME, (VOID*)(LPCTSTR)strUsername, strUsername.GetLength()) ;
                pF->SetOption (INTERNET_OPTION_PROXY_PASSWORD, (VOID*)(LPCTSTR)strPassword, strPassword.GetLength()) ;
                pF->SendRequest (NULL) ;
            }

            pF->QueryInfo (HTTP_QUERY_STATUS_CODE, str) ;
            if (str != _T("200"))
            {
                pF->Close() ;
                delete pF ;
                AfxThrowInternetException(1);
            }

            // confirm update
            pF->QueryInfo (HTTP_QUERY_LAST_MODIFIED, str) ;
            if (!pPara->pThis->df_Notify (GetMsg_CheckTime(), &WM_DLF_CHECKTIME(&pPara->strFileURL, &str)))
            {
                pF->Close() ;
                delete pF ;
                AfxThrowInternetException(1);
            }

            // start download
            pF->QueryInfo (HTTP_QUERY_CONTENT_LENGTH, str) ; // file's length
            pPara->pThis->df_Notify (GetMsg_StartDownload(), &pPara->strFileURL) ;

            if (_ttoi(str))
            {
                // know file's size
                int     nLen = (nBufLen = _ttoi(str)) ;
                char    * p = (pBuf = new char[nLen+8]) ;
                ZeroMemory (p, nLen+8) ;

                while (IsWindow(pPara->pThis->GetSafeHwnd()))
                {
                    // download 8K every
                    int   n = pF->Read (p, (nLen < 8192) ? nLen : 8192) ;
                    if (n <= 0)
                        break ; // success exit
                    p += n ; nLen -= n ;

                    pPara->pThis->df_Notify (GetMsg_Progress(), &WM_DLF_PROGRESS(&pPara->strFileURL, nBufLen-nLen, nBufLen)) ;
                }

                // interrupted
                if (nLen != 0)
                {
                    delete[] pBuf; pBuf=NULL;
                    nBufLen = 0 ;
                }
            }
            else
            {
                // don't know file's size, save context to a temp file.
                bstr_t   strFile = QueryTempFilePath() ;
                CFile    outFile (strFile, CFile::modeCreate|CFile::modeReadWrite) ;
                int      n = (int)pF->GetLength() ;
                while (IsWindow(pPara->pThis->GetSafeHwnd()) && n)
                {
                    char   * pa = new char[n] ;
                    n = pF->Read (pa, n) ;
                    outFile.Write (pa, n) ;
                    pPara->pThis->df_Notify (GetMsg_Progress(), &WM_DLF_PROGRESS(&pPara->strFileURL, (int)outFile.GetLength(), 0)) ;
                    n = (int)pF->GetLength() ;
                    delete[] pa ;
                }
                outFile.Close() ;

                // success
                if (n == 0)
                {
                    DWORD   dw ;
                    if (::InternetQueryDataAvailable ((HINTERNET)(*pF), &dw, 0, 0) && (dw == 0))
                    {
                        LoadFileToBuffer (strFile, pBuf, nBufLen) ;
                    }
                }
                ::DeleteFile(strFile) ;
            }

            pF->Close() ;
            delete pF ;
        }
        CATCH_ALL(e) {}
        END_CATCH_ALL

        if (pBuf)
        {
            pPara->pThis->df_Notify (GetMsg_DownFinished(), &WM_DLF_FINISHED(&pPara->strFileURL, pBuf, nBufLen)) ;
            delete[] pBuf ;
        }
        else
        {
            pPara->pThis->df_Notify (GetMsg_Error(), &pPara->strFileURL) ;
        }
        return 0 ;
    }
};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -