Sample code for 30+ languages & platforms
Lua Requires Chilkat v11.0.0+

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 Lua Downloads

Lua

    -- In the following call to loadlib, change the path (./chilkat.dll) to the relative or absolute directory where the chilkat.dll, chilkat.so, or chilkat.dylib is located.
    chilkat = assert(package.loadlib("./chilkat.dll", "luaopen_chilkat"))()
    print(chilkat._VERSION)

    local success = false

    --  This requires the Chilkat API to have been previously unlocked.
    --  See Global Unlock Sample for sample code.

    local http = chilkat.newHttp{}

    --  First get the size of the file to be downloaded.
    local url = "https://www.chilkatsoft.com/hamlet.xml"

    local resp = chilkat.newHttpResponse{}
    success = http:HttpNoBody("HEAD",url,resp)
    if success == false then
        print(http:LastErrorText())

    end

    local remoteFileSize = resp:ContentLength()

    print("Downloading ", remoteFileSize, " bytes...")

    --  Let's download in 4 chunks.
    --  (the last chunk will be whatever remains after the 1st 3 equal sized chunks)
    local 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..
    local http1 = chilkat.newHttp{}
    local http2 = chilkat.newHttp{}
    local http3 = chilkat.newHttp{}
    local http4 = chilkat.newHttp{}

    local sbRange = chilkat.newStringBuilder{}
    sbRange:SetString("bytes=<range-start>-<range-end>")
    local numReplaced = sbRange:ReplaceI("<range-start>",0)
    numReplaced = sbRange:ReplaceI("<range-end>",chunkSize - 1)
    print(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)
    print(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)
    print(sbRange:GetAsString())
    http3:SetRequestHeader("Range",sbRange:GetAsString())

    sbRange:SetString("bytes=<range-start>-")
    numReplaced = sbRange:ReplaceI("<range-start>",3 * chunkSize)
    print(sbRange:GetAsString())
    http4:SetRequestHeader("Range",sbRange:GetAsString())

    --  Start each range download
    local task1 = http1:DownloadAsync(url,"qa_output/chunk1.dat")
    task1:Run()

    local task2 = http2:DownloadAsync(url,"qa_output/chunk2.dat")
    task2:Run()

    local task3 = http3:DownloadAsync(url,"qa_output/chunk3.dat")
    task3:Run()

    local task4 = http4:DownloadAsync(url,"qa_output/chunk4.dat")
    task4:Run()

    --  Wait for the downloads to complete.
    local numLive = 4
    while numLive > 0 do
        numLive = 0
        if task1:Live() == true then
            numLive = numLive + 1
        end

        if task2:Live() == true then
            numLive = numLive + 1
        end

        if task3:Live() == true then
            numLive = numLive + 1
        end

        if task4:Live() == true then
            numLive = numLive + 1
        end

        if numLive > 0 then
            --  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.
    local numErrors = 0
    if task1:GetResultBool() == false then
        print(task1:ResultErrorText())
        numErrors = numErrors + 1
    end

    if task2:GetResultBool() == false then
        print(task2:ResultErrorText())
        numErrors = numErrors + 1
    end

    if task3:GetResultBool() == false then
        print(task3:ResultErrorText())
        numErrors = numErrors + 1
    end

    if task4:GetResultBool() == false then
        print(task4:ResultErrorText())
        numErrors = numErrors + 1
    end

    if numErrors > 0 then

    end

    --  All downloads were successful.
    --  Compose the file from the parts.
    local fac = chilkat.newFileAccess{}
    success = fac:ReassembleFile("qa_output","chunk","dat","qa_output/hamlet.xml")
    if success == false then
        print(fac:LastErrorText())
    else
        print("Success.")
    end

    --  Let's download in the regular way, and then compare files..
    success = http:Download(url,"qa_output/hamletRegular.xml")

    --  Compare files.
    local bSame = fac:FileContentsEqual("qa_output/hamlet.xml","qa_output/hamletRegular.xml")
    print("bSame = ", bSame)