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
(PureBasic) 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.
IncludeFile "CkHttpResponse.pb" IncludeFile "CkHttp.pb" IncludeFile "CkStringBuilder.pb" IncludeFile "CkTask.pb" IncludeFile "CkFileAccess.pb" Procedure ChilkatExample() ; This requires the Chilkat API to have been previously unlocked. ; See Global Unlock Sample for sample code. http.i = CkHttp::ckCreate() If http.i = 0 Debug "Failed to create object." ProcedureReturn EndIf success.i ; First get the size of the file to be downloaded. url.s = "https://www.chilkatsoft.com/hamlet.xml" resp.i = CkHttp::ckGetHead(http,url) If CkHttp::ckLastMethodSuccess(http) = 0 Debug CkHttp::ckLastErrorText(http) CkHttp::ckDispose(http) ProcedureReturn EndIf remoteFileSize.i = CkHttpResponse::ckContentLength(resp) CkHttpResponse::ckDispose(resp) Debug "Downloading " + Str(remoteFileSize) + " bytes..." ; Let's download in 4 chunks. ; (the last chunk will be whatever remains after the 1st 3 equal sized chunks) chunkSize.i = 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.i = CkHttp::ckCreate() If http1.i = 0 Debug "Failed to create object." ProcedureReturn EndIf http2.i = CkHttp::ckCreate() If http2.i = 0 Debug "Failed to create object." ProcedureReturn EndIf http3.i = CkHttp::ckCreate() If http3.i = 0 Debug "Failed to create object." ProcedureReturn EndIf http4.i = CkHttp::ckCreate() If http4.i = 0 Debug "Failed to create object." ProcedureReturn EndIf sbRange.i = CkStringBuilder::ckCreate() If sbRange.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkStringBuilder::ckSetString(sbRange,"bytes=<range-start>-<range-end>") numReplaced.i = CkStringBuilder::ckReplaceI(sbRange,"<range-start>",0) numReplaced = CkStringBuilder::ckReplaceI(sbRange,"<range-end>",chunkSize - 1) Debug CkStringBuilder::ckGetAsString(sbRange) CkHttp::ckSetRequestHeader(http1,"Range",CkStringBuilder::ckGetAsString(sbRange)) CkStringBuilder::ckSetString(sbRange,"bytes=<range-start>-<range-end>") numReplaced = CkStringBuilder::ckReplaceI(sbRange,"<range-start>",chunkSize) numReplaced = CkStringBuilder::ckReplaceI(sbRange,"<range-end>",2 * chunkSize - 1) Debug CkStringBuilder::ckGetAsString(sbRange) CkHttp::ckSetRequestHeader(http2,"Range",CkStringBuilder::ckGetAsString(sbRange)) CkStringBuilder::ckSetString(sbRange,"bytes=<range-start>-<range-end>") numReplaced = CkStringBuilder::ckReplaceI(sbRange,"<range-start>",2 * chunkSize) numReplaced = CkStringBuilder::ckReplaceI(sbRange,"<range-end>",3 * chunkSize - 1) Debug CkStringBuilder::ckGetAsString(sbRange) CkHttp::ckSetRequestHeader(http3,"Range",CkStringBuilder::ckGetAsString(sbRange)) CkStringBuilder::ckSetString(sbRange,"bytes=<range-start>-") numReplaced = CkStringBuilder::ckReplaceI(sbRange,"<range-start>",3 * chunkSize) Debug CkStringBuilder::ckGetAsString(sbRange) CkHttp::ckSetRequestHeader(http4,"Range",CkStringBuilder::ckGetAsString(sbRange)) ; Start each range download task1.i = CkHttp::ckDownloadAsync(http1,url,"qa_output/chunk1.dat") CkTask::ckRun(task1) task2.i = CkHttp::ckDownloadAsync(http2,url,"qa_output/chunk2.dat") CkTask::ckRun(task2) task3.i = CkHttp::ckDownloadAsync(http3,url,"qa_output/chunk3.dat") CkTask::ckRun(task3) task4.i = CkHttp::ckDownloadAsync(http4,url,"qa_output/chunk4.dat") CkTask::ckRun(task4) ; Wait for the downloads to complete. numLive.i = 4 While numLive > 0 numLive = 0 If CkTask::ckLive(task1) = 1 numLive = numLive + 1 EndIf If CkTask::ckLive(task2) = 1 numLive = numLive + 1 EndIf If CkTask::ckLive(task3) = 1 numLive = numLive + 1 EndIf If CkTask::ckLive(task4) = 1 numLive = numLive + 1 EndIf If numLive > 0 ; SleepMs is a convenience method to cause the caller to sleep for N millisec. ; It does not cause the given task to sleep.. CkTask::ckSleepMs(task1,10) EndIf Wend ; All should be downloaded now.. ; Examine the result of each Download. numErrors.i = 0 If CkTask::ckGetResultBool(task1) = 0 Debug CkTask::ckResultErrorText(task1) numErrors = numErrors + 1 EndIf If CkTask::ckGetResultBool(task2) = 0 Debug CkTask::ckResultErrorText(task2) numErrors = numErrors + 1 EndIf If CkTask::ckGetResultBool(task3) = 0 Debug CkTask::ckResultErrorText(task3) numErrors = numErrors + 1 EndIf If CkTask::ckGetResultBool(task4) = 0 Debug CkTask::ckResultErrorText(task4) numErrors = numErrors + 1 EndIf If numErrors > 0 CkTask::ckDispose(task1) CkTask::ckDispose(task2) CkTask::ckDispose(task3) CkTask::ckDispose(task4) CkHttp::ckDispose(http) CkHttp::ckDispose(http1) CkHttp::ckDispose(http2) CkHttp::ckDispose(http3) CkHttp::ckDispose(http4) CkStringBuilder::ckDispose(sbRange) ProcedureReturn EndIf ; All downloads were successful. ; Compose the file from the parts. fac.i = CkFileAccess::ckCreate() If fac.i = 0 Debug "Failed to create object." ProcedureReturn EndIf success = CkFileAccess::ckReassembleFile(fac,"qa_output","chunk","dat","qa_output/hamlet.xml") If success = 0 Debug CkFileAccess::ckLastErrorText(fac) Else Debug "Success." EndIf CkTask::ckDispose(task1) CkTask::ckDispose(task2) CkTask::ckDispose(task3) CkTask::ckDispose(task4) ; Let's download in the regular way, and then compare files.. success = CkHttp::ckDownload(http,url,"qa_output/hamletRegular.xml") ; Compare files. bSame.i = CkFileAccess::ckFileContentsEqual(fac,"qa_output/hamlet.xml","qa_output/hamletRegular.xml") Debug "bSame = " + Str(bSame) CkHttp::ckDispose(http) CkHttp::ckDispose(http1) CkHttp::ckDispose(http2) CkHttp::ckDispose(http3) CkHttp::ckDispose(http4) CkStringBuilder::ckDispose(sbRange) CkFileAccess::ckDispose(fac) ProcedureReturn EndProcedure |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.