www.gusucode.com > 一个视频压缩并通过网络来传送的源代码 > 一个视频压缩并通过网络来传送的源代码/断点续传和多线程VC源码/code/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(void) { if(FOnError) FOnError(FOwner,FIndex); } //---------------------------------------------------------------------------