DataFlex
DataFlex
HTTP Download in Parallel with Simultaneous Range Requests
See more HTTP Examples
Demonstrates how to download a large file with parallel simultaneous requests, where each request downloads a segment (range) of the remote file.Chilkat DataFlex Downloads
Use ChilkatAx-win32.pkg
Procedure Test
Boolean iSuccess
Handle hoHttp
String sUrl
Variant vResp
Handle hoResp
Integer iRemoteFileSize
Integer iChunkSize
Handle hoHttp1
Handle hoHttp2
Handle hoHttp3
Handle hoHttp4
Handle hoSbRange
Integer iNumReplaced
Variant vTask1
Handle hoTask1
Variant vTask2
Handle hoTask2
Variant vTask3
Handle hoTask3
Variant vTask4
Handle hoTask4
Integer iNumLive
Integer iNumErrors
Handle hoFac
Boolean iBSame
String sTemp1
Boolean bTemp1
Move False To iSuccess
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
Get Create (RefClass(cComChilkatHttp)) To hoHttp
If (Not(IsComObjectCreated(hoHttp))) Begin
Send CreateComObject of hoHttp
End
// First get the size of the file to be downloaded.
Move "https://www.chilkatsoft.com/hamlet.xml" To sUrl
Get Create (RefClass(cComChilkatHttpResponse)) To hoResp
If (Not(IsComObjectCreated(hoResp))) Begin
Send CreateComObject of hoResp
End
Get pvComObject of hoResp to vResp
Get ComHttpNoBody Of hoHttp "HEAD" sUrl vResp To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoHttp To sTemp1
Showln sTemp1
Procedure_Return
End
Get ComContentLength Of hoResp To iRemoteFileSize
Showln "Downloading " iRemoteFileSize " bytes..."
// Let's download in 4 chunks.
// (the last chunk will be whatever remains after the 1st 3 equal sized chunks)
Move (iRemoteFileSize / 4) To iChunkSize
// 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..
Get Create (RefClass(cComChilkatHttp)) To hoHttp1
If (Not(IsComObjectCreated(hoHttp1))) Begin
Send CreateComObject of hoHttp1
End
Get Create (RefClass(cComChilkatHttp)) To hoHttp2
If (Not(IsComObjectCreated(hoHttp2))) Begin
Send CreateComObject of hoHttp2
End
Get Create (RefClass(cComChilkatHttp)) To hoHttp3
If (Not(IsComObjectCreated(hoHttp3))) Begin
Send CreateComObject of hoHttp3
End
Get Create (RefClass(cComChilkatHttp)) To hoHttp4
If (Not(IsComObjectCreated(hoHttp4))) Begin
Send CreateComObject of hoHttp4
End
Get Create (RefClass(cComChilkatStringBuilder)) To hoSbRange
If (Not(IsComObjectCreated(hoSbRange))) Begin
Send CreateComObject of hoSbRange
End
Get ComSetString Of hoSbRange "bytes=<range-start>-<range-end>" To iSuccess
Get ComReplaceI Of hoSbRange "<range-start>" 0 To iNumReplaced
Get ComReplaceI Of hoSbRange "<range-end>" (iChunkSize - 1) To iNumReplaced
Get ComGetAsString Of hoSbRange To sTemp1
Showln sTemp1
Get ComGetAsString Of hoSbRange To sTemp1
Send ComSetRequestHeader To hoHttp1 "Range" sTemp1
Get ComSetString Of hoSbRange "bytes=<range-start>-<range-end>" To iSuccess
Get ComReplaceI Of hoSbRange "<range-start>" iChunkSize To iNumReplaced
Get ComReplaceI Of hoSbRange "<range-end>" (2 * iChunkSize - 1) To iNumReplaced
Get ComGetAsString Of hoSbRange To sTemp1
Showln sTemp1
Get ComGetAsString Of hoSbRange To sTemp1
Send ComSetRequestHeader To hoHttp2 "Range" sTemp1
Get ComSetString Of hoSbRange "bytes=<range-start>-<range-end>" To iSuccess
Get ComReplaceI Of hoSbRange "<range-start>" (2 * iChunkSize) To iNumReplaced
Get ComReplaceI Of hoSbRange "<range-end>" (3 * iChunkSize - 1) To iNumReplaced
Get ComGetAsString Of hoSbRange To sTemp1
Showln sTemp1
Get ComGetAsString Of hoSbRange To sTemp1
Send ComSetRequestHeader To hoHttp3 "Range" sTemp1
Get ComSetString Of hoSbRange "bytes=<range-start>-" To iSuccess
Get ComReplaceI Of hoSbRange "<range-start>" (3 * iChunkSize) To iNumReplaced
Get ComGetAsString Of hoSbRange To sTemp1
Showln sTemp1
Get ComGetAsString Of hoSbRange To sTemp1
Send ComSetRequestHeader To hoHttp4 "Range" sTemp1
// Start each range download
Get ComDownloadAsync Of hoHttp1 sUrl "qa_output/chunk1.dat" To vTask1
If (IsComObject(vTask1)) Begin
Get Create (RefClass(cComChilkatTask)) To hoTask1
Set pvComObject Of hoTask1 To vTask1
End
Get ComRun Of hoTask1 To iSuccess
Get ComDownloadAsync Of hoHttp2 sUrl "qa_output/chunk2.dat" To vTask2
If (IsComObject(vTask2)) Begin
Get Create (RefClass(cComChilkatTask)) To hoTask2
Set pvComObject Of hoTask2 To vTask2
End
Get ComRun Of hoTask2 To iSuccess
Get ComDownloadAsync Of hoHttp3 sUrl "qa_output/chunk3.dat" To vTask3
If (IsComObject(vTask3)) Begin
Get Create (RefClass(cComChilkatTask)) To hoTask3
Set pvComObject Of hoTask3 To vTask3
End
Get ComRun Of hoTask3 To iSuccess
Get ComDownloadAsync Of hoHttp4 sUrl "qa_output/chunk4.dat" To vTask4
If (IsComObject(vTask4)) Begin
Get Create (RefClass(cComChilkatTask)) To hoTask4
Set pvComObject Of hoTask4 To vTask4
End
Get ComRun Of hoTask4 To iSuccess
// Wait for the downloads to complete.
Move 4 To iNumLive
While (iNumLive > 0)
Move 0 To iNumLive
Get ComLive Of hoTask1 To bTemp1
If (bTemp1 = True) Begin
Move (iNumLive + 1) To iNumLive
End
Get ComLive Of hoTask2 To bTemp1
If (bTemp1 = True) Begin
Move (iNumLive + 1) To iNumLive
End
Get ComLive Of hoTask3 To bTemp1
If (bTemp1 = True) Begin
Move (iNumLive + 1) To iNumLive
End
Get ComLive Of hoTask4 To bTemp1
If (bTemp1 = True) Begin
Move (iNumLive + 1) To iNumLive
End
If (iNumLive > 0) Begin
// SleepMs is a convenience method to cause the caller to sleep for N millisec.
// It does not cause the given task to sleep..
Send ComSleepMs To hoTask1 10
End
Loop
// All should be downloaded now..
// Examine the result of each Download.
Move 0 To iNumErrors
Get ComGetResultBool Of hoTask1 To bTemp1
If (bTemp1 = False) Begin
Get ComResultErrorText Of hoTask1 To sTemp1
Showln sTemp1
Move (iNumErrors + 1) To iNumErrors
End
Get ComGetResultBool Of hoTask2 To bTemp1
If (bTemp1 = False) Begin
Get ComResultErrorText Of hoTask2 To sTemp1
Showln sTemp1
Move (iNumErrors + 1) To iNumErrors
End
Get ComGetResultBool Of hoTask3 To bTemp1
If (bTemp1 = False) Begin
Get ComResultErrorText Of hoTask3 To sTemp1
Showln sTemp1
Move (iNumErrors + 1) To iNumErrors
End
Get ComGetResultBool Of hoTask4 To bTemp1
If (bTemp1 = False) Begin
Get ComResultErrorText Of hoTask4 To sTemp1
Showln sTemp1
Move (iNumErrors + 1) To iNumErrors
End
If (iNumErrors > 0) Begin
Send Destroy of hoTask1
Send Destroy of hoTask2
Send Destroy of hoTask3
Send Destroy of hoTask4
Procedure_Return
End
// All downloads were successful.
// Compose the file from the parts.
Get Create (RefClass(cComCkFileAccess)) To hoFac
If (Not(IsComObjectCreated(hoFac))) Begin
Send CreateComObject of hoFac
End
Get ComReassembleFile Of hoFac "qa_output" "chunk" "dat" "qa_output/hamlet.xml" To iSuccess
If (iSuccess = False) Begin
Get ComLastErrorText Of hoFac To sTemp1
Showln sTemp1
End
Else Begin
Showln "Success."
End
Send Destroy of hoTask1
Send Destroy of hoTask2
Send Destroy of hoTask3
Send Destroy of hoTask4
// Let's download in the regular way, and then compare files..
Get ComDownload Of hoHttp sUrl "qa_output/hamletRegular.xml" To iSuccess
// Compare files.
Get ComFileContentsEqual Of hoFac "qa_output/hamlet.xml" "qa_output/hamletRegular.xml" To iBSame
Showln "bSame = " iBSame
End_Procedure