Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(Delphi ActiveX) HTTP Download in Parallel with Simultaneous Range RequestsDemonstrates how to download a large file with parallel simultaneous requests, where each request downloads a segment (range) of the remote file.
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Chilkat_TLB; ... procedure TForm1.Button1Click(Sender: TObject); var http: TChilkatHttp; success: Integer; url: WideString; resp: IChilkatHttpResponse; remoteFileSize: Integer; chunkSize: Integer; http1: TChilkatHttp; http2: TChilkatHttp; http3: TChilkatHttp; http4: TChilkatHttp; sbRange: TChilkatStringBuilder; numReplaced: Integer; task1: IChilkatTask; task2: IChilkatTask; task3: IChilkatTask; task4: IChilkatTask; numLive: Integer; numErrors: Integer; fac: TCkFileAccess; bSame: Integer; begin // This requires the Chilkat API to have been previously unlocked. // See Global Unlock Sample for sample code. http := TChilkatHttp.Create(Self); // First get the size of the file to be downloaded. url := 'https://www.chilkatsoft.com/hamlet.xml'; resp := http.GetHead(url); if (http.LastMethodSuccess = 0) then begin Memo1.Lines.Add(http.LastErrorText); Exit; end; remoteFileSize := resp.ContentLength; Memo1.Lines.Add('Downloading ' + IntToStr(remoteFileSize) + ' bytes...'); // Let's download in 4 chunks. // (the last chunk will be whatever remains after the 1st 3 equal sized chunks) chunkSize := remoteFileSize / 4; // The Range header is used to download a range from a resource // Range: bytes=<range-start>-<range-end> // or // Range: bytes=<range-start>- // We're writing code this way for clarity.. http1 := TChilkatHttp.Create(Self); http2 := TChilkatHttp.Create(Self); http3 := TChilkatHttp.Create(Self); http4 := TChilkatHttp.Create(Self); sbRange := TChilkatStringBuilder.Create(Self); sbRange.SetString('bytes=<range-start>-<range-end>'); numReplaced := sbRange.ReplaceI('<range-start>',0); numReplaced := sbRange.ReplaceI('<range-end>',chunkSize - 1); Memo1.Lines.Add(sbRange.GetAsString()); http1.SetRequestHeader('Range',sbRange.GetAsString()); sbRange.SetString('bytes=<range-start>-<range-end>'); numReplaced := sbRange.ReplaceI('<range-start>',chunkSize); numReplaced := sbRange.ReplaceI('<range-end>',2 * chunkSize - 1); Memo1.Lines.Add(sbRange.GetAsString()); http2.SetRequestHeader('Range',sbRange.GetAsString()); sbRange.SetString('bytes=<range-start>-<range-end>'); numReplaced := sbRange.ReplaceI('<range-start>',2 * chunkSize); numReplaced := sbRange.ReplaceI('<range-end>',3 * chunkSize - 1); Memo1.Lines.Add(sbRange.GetAsString()); http3.SetRequestHeader('Range',sbRange.GetAsString()); sbRange.SetString('bytes=<range-start>-'); numReplaced := sbRange.ReplaceI('<range-start>',3 * chunkSize); Memo1.Lines.Add(sbRange.GetAsString()); http4.SetRequestHeader('Range',sbRange.GetAsString()); // Start each range download task1 := http1.DownloadAsync(url,'qa_output/chunk1.dat'); task1.Run(); task2 := http2.DownloadAsync(url,'qa_output/chunk2.dat'); task2.Run(); task3 := http3.DownloadAsync(url,'qa_output/chunk3.dat'); task3.Run(); task4 := http4.DownloadAsync(url,'qa_output/chunk4.dat'); task4.Run(); // Wait for the downloads to complete. numLive := 4; while numLive > 0 do begin numLive := 0; if (task1.Live = 1) then begin numLive := numLive + 1; end; if (task2.Live = 1) then begin numLive := numLive + 1; end; if (task3.Live = 1) then begin numLive := numLive + 1; end; if (task4.Live = 1) then begin numLive := numLive + 1; end; if (numLive > 0) then begin // SleepMs is a convenience method to cause the caller to sleep for N millisec. // It does not cause the given task to sleep.. task1.SleepMs(10); end; end; // All should be downloaded now.. // Examine the result of each Download. numErrors := 0; if (task1.GetResultBool() = 0) then begin Memo1.Lines.Add(task1.ResultErrorText); numErrors := numErrors + 1; end; if (task2.GetResultBool() = 0) then begin Memo1.Lines.Add(task2.ResultErrorText); numErrors := numErrors + 1; end; if (task3.GetResultBool() = 0) then begin Memo1.Lines.Add(task3.ResultErrorText); numErrors := numErrors + 1; end; if (task4.GetResultBool() = 0) then begin Memo1.Lines.Add(task4.ResultErrorText); numErrors := numErrors + 1; end; if (numErrors > 0) then begin Exit; end; // All downloads were successful. // Compose the file from the parts. fac := TCkFileAccess.Create(Self); success := fac.ReassembleFile('qa_output','chunk','dat','qa_output/hamlet.xml'); if (success = 0) then begin Memo1.Lines.Add(fac.LastErrorText); end else begin Memo1.Lines.Add('Success.'); end; // Let's download in the regular way, and then compare files.. success := http.Download(url,'qa_output/hamletRegular.xml'); // Compare files. bSame := fac.FileContentsEqual('qa_output/hamlet.xml','qa_output/hamletRegular.xml'); Memo1.Lines.Add('bSame = ' + IntToStr(Ord(bSame))); end; |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.