Sample code for 30+ languages & platforms
Perl

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

Perl
use chilkat();

$success = 0;

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

$http = chilkat::CkHttp->new();

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

$resp = chilkat::CkHttpResponse->new();
$success = $http->HttpNoBody("HEAD",$url,$resp);
if ($success == 0) {
    print $http->lastErrorText() . "\r\n";
    exit;
}

$remoteFileSize = $resp->get_ContentLength();

print "Downloading " . $remoteFileSize . " bytes..." . "\r\n";

# 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::CkHttp->new();
$http2 = chilkat::CkHttp->new();
$http3 = chilkat::CkHttp->new();
$http4 = chilkat::CkHttp->new();

$sbRange = chilkat::CkStringBuilder->new();
$sbRange->SetString("bytes=<range-start>-<range-end>");
$numReplaced = $sbRange->ReplaceI("<range-start>",0);
$numReplaced = $sbRange->ReplaceI("<range-end>",$chunkSize - 1);
print $sbRange->getAsString() . "\r\n";
$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() . "\r\n";
$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() . "\r\n";
$http3->SetRequestHeader("Range",$sbRange->getAsString());

$sbRange->SetString("bytes=<range-start>-");
$numReplaced = $sbRange->ReplaceI("<range-start>",3 * $chunkSize);
print $sbRange->getAsString() . "\r\n";
$http4->SetRequestHeader("Range",$sbRange->getAsString());

# Start each range download
# task1 is a Task
$task1 = $http1->DownloadAsync($url,"qa_output/chunk1.dat");
$task1->Run();

# task2 is a Task
$task2 = $http2->DownloadAsync($url,"qa_output/chunk2.dat");
$task2->Run();

# task3 is a Task
$task3 = $http3->DownloadAsync($url,"qa_output/chunk3.dat");
$task3->Run();

# task4 is a Task
$task4 = $http4->DownloadAsync($url,"qa_output/chunk4.dat");
$task4->Run();

# Wait for the downloads to complete.
$numLive = 4;
while ($numLive > 0) {
    $numLive = 0;
    if ($task1->get_Live() == 1) {
        $numLive = $numLive + 1;
    }

    if ($task2->get_Live() == 1) {
        $numLive = $numLive + 1;
    }

    if ($task3->get_Live() == 1) {
        $numLive = $numLive + 1;
    }

    if ($task4->get_Live() == 1) {
        $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() == 0) {
    print $task1->resultErrorText() . "\r\n";
    $numErrors = $numErrors + 1;
}

if ($task2->GetResultBool() == 0) {
    print $task2->resultErrorText() . "\r\n";
    $numErrors = $numErrors + 1;
}

if ($task3->GetResultBool() == 0) {
    print $task3->resultErrorText() . "\r\n";
    $numErrors = $numErrors + 1;
}

if ($task4->GetResultBool() == 0) {
    print $task4->resultErrorText() . "\r\n";
    $numErrors = $numErrors + 1;
}

if ($numErrors > 0) {

    exit;
}

# All downloads were successful.
# Compose the file from the parts.
$fac = chilkat::CkFileAccess->new();
$success = $fac->ReassembleFile("qa_output","chunk","dat","qa_output/hamlet.xml");
if ($success == 0) {
    print $fac->lastErrorText() . "\r\n";
}
else {
    print "Success." . "\r\n";
}

# 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");
print "bSame = " . $bSame . "\r\n";