📄 controller_downloadfile.h
字号:
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 + -