隨着Delphi 10.2.3的發布,隨之帶來更穩定、更完善的版本。今天借官方的例子,解讀一下如何實現Http異步下載並顯示下載進度。
使用的核心組件是THttpClient,首先建立一個THttpClient對象FClient,用他來執行下載任務。
procedure TFormDownloadDemo.FormCreate(Sender: TObject); begin FClient := THTTPClient.Create; FClient.OnReceiveData := ReceiveDataEvent; end;
我們看到,這里為FClient實現了OnReceiveData事件,目的用來顯示下載進度,注意這個事件在異步執行Http下載時,是在線程中執行的。來看一下具體的實現代碼:
procedure TFormDownloadDemo.ReceiveDataEvent(const Sender: TObject; AContentLength, AReadCount: Int64; var Abort: Boolean); var LTime: Cardinal; LSpeed: Integer; begin LTime := TThread.GetTickCount - FGlobalStart;//計算用時 LSpeed := (AReadCount * 1000) div LTime;//計算下載速度 TThread.Queue(nil, procedure begin ProgressBarDownload.Value := AReadCount;//顯示下載進度 LabelGlobalSpeed.Text := Format('Global speed: %d KB/s', [LSpeed div 1024]);//顯示下載速度 end); end;
AContentLength:下載內容的長度
AReadCount:已經下載的字節數
在這個事件中,計算每秒下載字節數,並用ProgressBarDownload可視組件來顯示進度。
因為這個事件在線程中執行,所以同步界面上的ProgressBarDownload進度條時,用了TThread.Queue同步主線程。
接下來,實現具體的下載方法,並用一個按鈕來執行這個方法,執行下載任務:
procedure TFormDownloadDemo.SampleDownload; var URL: string; LResponse: IHTTPResponse; LFileName: string; LSize: Int64; begin LFileName := TPath.Combine(TPath.GetDocumentsPath, EditFileName.Text);//本地保存的文件地址 try URL := EditURL.Text;//文件的URL地址 LResponse := FClient.Head(URL);//取得IHTTPResponse接口,通過該接口獲得下載文件的長度 LSize := LResponse.ContentLength;//求出下載內容的長度 Memo1.Lines.Add(Format('Head response: %d - %s', [LResponse.StatusCode, LResponse.StatusText])); LResponse := nil; ProgressBarDownload.Max := LSize;//設置進度條的最大值 ProgressBarDownload.Min := 0; ProgressBarDownload.Value := 0; LabelGlobalSpeed.Text := 'Global speed: 0 KB/s'; Memo1.Lines.Add(Format('Downloading: "%s" (%d Bytes) into "%s"' , [EditFileName.Text, LSize, LFileName])); // 建立一個文件流FDownloadStream,准備用於保存下載內容 FDownloadStream := TFileStream.Create(LFileName, fmCreate);//建立下載文件流 FDownloadStream.Position := 0; FGlobalStart := TThread.GetTickCount;//取開始下載時間,用於計算下載速度 // 開始下載 FAsyncResult := FClient.BeginGet(DoEndDownload, URL, FDownloadStream); finally BStopDownload.Enabled := FAsyncResult <> nil;//下載過程中允許中止下載 BStartDownload.Enabled := FAsyncResult = nil;//下載完成后允許開始下載 end; end;
上面對下載方法進行了注釋,但還有必要說一下這個具體的下載調用所要實現的目的:
FAsyncResult := FClient.BeginGet(DoEndDownload, URL, FDownloadStream);
我們看到,用FClient.BeginGet執行下載,同時傳進去三個參數:
DoEndDownload:一個方法,下載完成后調用
URL:下載內容的URL
FDownLoadStream:保存下載內容的文件流。
重點在於DoEndDownload方法的實現:
procedure TFormDownloadDemo.DoEndDownload(const AsyncResult: IAsyncResult); var LAsyncResponse: IHTTPResponse; begin try LAsyncResponse := THTTPClient.EndAsyncHTTP(AsyncResult);//通過傳進來的參數,取得異步響應接口 TThread.Synchronize(nil, procedure begin Memo1.Lines.Add('Download Finished!'); Memo1.Lines.Add(Format('Status: %d - %s', [LAsyncResponse.StatusCode, LAsyncResponse.StatusText])); end); finally LAsyncResponse := nil; FreeandNil(FDownloadStream); BStopDownload.Enabled := False; BStartDownload.Enabled := True; end; end;
首先這個方法,要聲明成下面這樣:
procedure (const ASyncResult: IAsyncResult);
然后我們看到,在具體的實現中,使用了傳進來的參數ASyncResult,取得下載后接口LAsyncResponse,並通過該接口,進一步取得下載后的信息。
然后做的第二件事是釋放保存下載的文件流FDownloadStream,最后設置開始下載按與中止下載按鈕的狀態。
同樣,我們也看到,這里使用了TThread.Synchronize來同步界面,那說明這個方法也是在線程中執行的。
好了,在線程中下載文件並在界面上顯示下載進度的整個過程基本就說完了。具體的例子代碼在
C:\Users\Public\Documents\Embarcadero\Studio\19.0\Samples\Object Pascal\RTL\HttpAsyncDownload
這個例子是哪一個版本支持的,我也記不清,反正今天看到,全當10.2.3帶的好了,其實這已不重要,重要的是,參考他來實現自己的http異步下載!
眾所周知,這是一個跨平台的版本,同樣的實現,可同時用於Android,IOS,Windows,OSX,Linux...這才是真正讓人興奮的事情。現在,我要集成到我的項目中去了...