Go
Go
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 Go Downloads
success := false
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
http := chilkat.NewHttp()
// First get the size of the file to be downloaded.
url := "https://www.chilkatsoft.com/hamlet.xml"
resp := chilkat.NewHttpResponse()
success = http.HttpNoBody("HEAD",url,resp)
if success == false {
fmt.Println(http.LastErrorText())
http.DisposeHttp()
resp.DisposeHttpResponse()
return
}
remoteFileSize := resp.ContentLength()
fmt.Println("Downloading ", 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 := chilkat.NewHttp()
http2 := chilkat.NewHttp()
http3 := chilkat.NewHttp()
http4 := chilkat.NewHttp()
sbRange := chilkat.NewStringBuilder()
sbRange.SetString("bytes=<range-start>-<range-end>")
numReplaced := sbRange.ReplaceI("<range-start>",0)
numReplaced = sbRange.ReplaceI("<range-end>",chunkSize - 1)
fmt.Println(*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)
fmt.Println(*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)
fmt.Println(*sbRange.GetAsString())
http3.SetRequestHeader("Range",*sbRange.GetAsString())
sbRange.SetString("bytes=<range-start>-")
numReplaced = sbRange.ReplaceI("<range-start>",3 * chunkSize)
fmt.Println(*sbRange.GetAsString())
http4.SetRequestHeader("Range",*sbRange.GetAsString())
// Start each range download
c := make(chan *chilkat.Task)
go http1.DownloadAsync(url,"qa_output/chunk1.dat",c)
task1 := <-c
c := make(chan *chilkat.Task)
go http2.DownloadAsync(url,"qa_output/chunk2.dat",c)
task2 := <-c
c := make(chan *chilkat.Task)
go http3.DownloadAsync(url,"qa_output/chunk3.dat",c)
task3 := <-c
c := make(chan *chilkat.Task)
go http4.DownloadAsync(url,"qa_output/chunk4.dat",c)
task4 := <-c
// Wait for the downloads to complete.
numLive := 4
for numLive > 0 {
numLive = 0
if task1.Live() == true {
numLive = numLive + 1
}
if task2.Live() == true {
numLive = numLive + 1
}
if task3.Live() == true {
numLive = numLive + 1
}
if task4.Live() == true {
numLive = numLive + 1
}
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..
task1.SleepMs(10)
}
}
// All should be downloaded now..
// Examine the result of each Download.
numErrors := 0
if task1.GetResultBool() == false {
fmt.Println(task1.ResultErrorText())
numErrors = numErrors + 1
}
if task2.GetResultBool() == false {
fmt.Println(task2.ResultErrorText())
numErrors = numErrors + 1
}
if task3.GetResultBool() == false {
fmt.Println(task3.ResultErrorText())
numErrors = numErrors + 1
}
if task4.GetResultBool() == false {
fmt.Println(task4.ResultErrorText())
numErrors = numErrors + 1
}
if numErrors > 0 {
task1.DisposeTask()
task2.DisposeTask()
task3.DisposeTask()
task4.DisposeTask()
http.DisposeHttp()
resp.DisposeHttpResponse()
http1.DisposeHttp()
http2.DisposeHttp()
http3.DisposeHttp()
http4.DisposeHttp()
sbRange.DisposeStringBuilder()
task1.DisposeTask()
task2.DisposeTask()
task3.DisposeTask()
task4.DisposeTask()
return
}
// All downloads were successful.
// Compose the file from the parts.
fac := chilkat.NewFileAccess()
success = fac.ReassembleFile("qa_output","chunk","dat","qa_output/hamlet.xml")
if success == false {
fmt.Println(fac.LastErrorText())
} else {
fmt.Println("Success.")
}
task1.DisposeTask()
task2.DisposeTask()
task3.DisposeTask()
task4.DisposeTask()
// 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")
fmt.Println("bSame = ", bSame)
http.DisposeHttp()
resp.DisposeHttpResponse()
http1.DisposeHttp()
http2.DisposeHttp()
http3.DisposeHttp()
http4.DisposeHttp()
sbRange.DisposeStringBuilder()
task1.DisposeTask()
task2.DisposeTask()
task3.DisposeTask()
task4.DisposeTask()
fac.DisposeFileAccess()