?? thttpgetthread.~cpp
字號:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "THttpGetThread.h"
#pragma package(smart_init)
#pragma link "wininet.lib"
//---------------------------------------------------------------------------
int GetFileSize(const AnsiString &FileName)
{
int FileSize=0;
HANDLE hFile=CreateFile(FileName.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
FileSize=GetFileSize(hFile,NULL);
CloseHandle(hFile);
}
return FileSize;
}
//---------------------------------------------------------------------------
__fastcall THttpGetThread::THttpGetThread(TObject *Owner): TThread(true)
{
FreeOnTerminate = True; // 自動刪除
FRepeatCount=5;
FIndex=0;
FOwner=Owner;
FFromBreakpoint=false;
FSuccess=false;
FConnected=false;
iFileHandle=-1;
FFileSize=-2;
dwStart=0;
dwTotal=0;
}
//---------------------------------------------------------------------------
void __fastcall THttpGetThread::Execute()
{
for(int i=0;i<FRepeatCount;i++)
{
StartHttpGet();
GetWebFileSize();
SetFilePointer();
DoHttpGet();
EndHttpGet();
if(FSuccess)break;
}
// 調用完成事件
if(FSuccess)
DoOnComplete();
//else DoOnError();
}
//---------------------------------------------------------------------------
// 從URL中提取主機名稱和下載文件路徑
void THttpGetThread::ParseURL(void)
{
AnsiString URL=FURL;
int i=URL.Pos("http://");
if(i>0)
{
URL.Delete(1, 7);
}
i=URL.Pos("/");
FHostName = URL.SubString(1, i-1);
FDownPath = URL.SubString(i, URL.Length());
}
//---------------------------------------------------------------------------
// 打開Internet句柄,初使化下載環境
void THttpGetThread::StartHttpGet(void)
{
if(FConnected)return;
ParseURL();
try
{
// 1.建立會話
FhSession = InternetOpen("http-get-demo",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL,NULL,
0); // 同步方式
if( FhSession==NULL)throw(Exception("Error:InterOpen"));
DoOnStatusText("ok:InterOpen");
// 2.建立連接
FhConnect=InternetConnect(FhSession,
FHostName.c_str(),
INTERNET_DEFAULT_HTTP_PORT,
NULL,NULL,
INTERNET_SERVICE_HTTP, 0, 0);
if(FhConnect==NULL)throw(Exception("Error:InternetConnect"));
DoOnStatusText("ok:InternetConnect");
// 3.初使化下載請求
const char *FAcceptTypes = "*/*";
FhRequest = HttpOpenRequest(FhConnect,
"GET",
FDownPath.c_str(),
"HTTP/1.0",
NULL,
&FAcceptTypes,
INTERNET_FLAG_RELOAD,
0);
if( FhRequest==NULL)throw(Exception("Error:HttpOpenRequest"));
DoOnStatusText("ok:HttpOpenRequest");
// 4.發送下載請求
HttpSendRequest(FhRequest, NULL, 0, NULL, 0);
DoOnStatusText("ok:HttpSendRequest");
FConnected=true;
}catch(Exception &exception)
{
EndHttpGet();
DoOnStatusText(exception.Message);
}
}
//---------------------------------------------------------------------------
int __fastcall THttpGetThread::GetWebFileSize(void)
{
if(FFileSize>-2)return FFileSize;
FFileSize=-1;
if(FConnected==false)StartHttpGet();
if(FConnected==false)return FFileSize;
try
{
// 取得文件的大小
DWORD BufLen=HTTPGET_BUFFER_MAX;
DWORD dwIndex=0;
bool RetQueryInfo=HttpQueryInfo(FhRequest,
HTTP_QUERY_CONTENT_LENGTH,
Buffer, &BufLen,
&dwIndex);
if( RetQueryInfo==false) throw(Exception("Error:HttpQueryInfo"));
DoOnStatusText("ok:HttpQueryInfo");
FFileSize=StrToInt(Buffer); // 文件大小
DoOnGetFileSize(FFileSize);
}catch(Exception &exception)
{
DoOnStatusText(exception.Message);
}
return FFileSize;
}
//---------------------------------------------------------------------------
bool __fastcall THttpGetThread::SetFilePointer(void)
{
int Size=GetWebFileSize();
if(Size<0)return false;
if(dwStart==0)return true;
try
{
// 調整文件指針
bool ReadReturn=InternetSetFilePointer(FhRequest,
dwStart,NULL,FILE_BEGIN,0);
if( ReadReturn==false) throw(Exception("Error:InternetSetFilePointer"));
DoOnStatusText("ok:InternetSetFilePointer");
return true;
}catch(Exception &exception)
{
DoOnStatusText(exception.Message);
}
return false;
}
//---------------------------------------------------------------------------
// 打開輸出文件,以保存下載的數據
DWORD THttpGetThread::OpenOutFile(void)
{
try
{
// 打開輸出文件,準備保存下載的數據
if(FileExists(FOutFileName))
{
if(FFromBreakpoint) // 使用斷點續傳
{
DWORD dwCount=GetFileSize(FOutFileName);
if(dwCount>0)
{
iFileHandle=FileOpen(FOutFileName,fmOpenWrite);
FileSeek(iFileHandle,0,2); // 移動文件指針到末尾
if(iFileHandle==-1) throw(Exception("Error:FileCreate"));
DoOnStatusText("ok:OpenFile");
return dwCount;
}
}
DeleteFile(FOutFileName);
}
iFileHandle=FileCreate(FOutFileName);
if(iFileHandle==-1) throw(Exception("Error:FileCreate"));
DoOnStatusText("ok:CreateFile");
}catch(Exception &exception)
{
DoOnStatusText(exception.Message);
}
return 0;
}
//---------------------------------------------------------------------------
// 執行下載過程
void THttpGetThread::DoHttpGet(void)
{
if(FConnected==false)return;
DWORD dwCount=OpenOutFile();
if(dwCount>0) // 調整文件指針
{
dwStart = dwStart + dwCount;
if(!SetFilePointer()) // 服務器不支持操作
{
// 清除輸出文件
FileSeek(iFileHandle,0,0); // 移動文件指針到頭部
}
}
try
{
// 發出下載事件
DoOnStatusText("StartGet:InternetReadFile");
// 讀取數據
DWORD dwRequest; // 請求下載的字節數
DWORD dwRead; // 實際讀出的字節數
dwRequest=HTTPGET_BUFFER_MAX;
while(true)
{
Application->ProcessMessages();
// 修正需要下載的字節數,使得dwRequest + dwCount<dwTotal
if(dwTotal>0) // dwTotal<=0表示下載到文件結束
{
if(dwRequest+dwCount>dwTotal)
dwRequest=dwTotal-dwCount;
}
bool ReadReturn = InternetReadFile(FhRequest,
(LPVOID)Buffer,
dwRequest,
&dwRead);
if(!ReadReturn)break;
if(dwRead==0)break;
// 保存數據
Buffer[dwRead]='\0';
FileWrite(iFileHandle, Buffer, dwRead);
dwCount = dwCount + dwRead;
// 發出下載進程事件
DoOnProgress(dwCount);
if(dwTotal>0) // Count<=0表示下載到文件結束
{
if(dwCount>=dwTotal)break;
}
}
}catch(Exception &exception)
{
DoOnStatusText(exception.Message);
}
FileClose(iFileHandle);
DoOnStatusText("End:InternetReadFile");
if(dwCount==dwTotal)FSuccess=true;
}
//---------------------------------------------------------------------------
// 關閉Internet句柄
void THttpGetThread::EndHttpGet(void)
{
if(FConnected)
{
DoOnStatusText("Closing:InternetConnect");
try
{
InternetCloseHandle(FhRequest);
InternetCloseHandle(FhConnect);
InternetCloseHandle(FhSession);
}catch(...){}
FhSession=NULL;
FhConnect=NULL;
FhRequest=NULL;
FConnected=false;
DoOnStatusText("Closed:InternetConnect");
}
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
void THttpGetThread::DoOnGetFileSize(int Size)
{
if(FOnGetFileSize)
FOnGetFileSize(FOwner,Size);
}
//---------------------------------------------------------------------------
void THttpGetThread::DoOnProgress(int Position)
{
if(FOnProgress)
FOnProgress(FOwner,Position,dwTotal,FIndex);
}
//---------------------------------------------------------------------------
void THttpGetThread::DoOnStatusText(AnsiString Text)
{
if(FOnStatusText)
FOnStatusText(FOwner,Text,FIndex);
}
//---------------------------------------------------------------------------
void THttpGetThread::DoOnComplete(void)
{
if(FOnComplete)
FOnComplete(FOwner,FIndex);
}
//---------------------------------------------------------------------------
void THttpGetThread::DoOnError(int errorcode)
{
if(FOnError)
FOnError(FOwner,errorcode);
}
//---------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -