Sample code for 30+ languages & platforms
C#

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 C# Downloads

C#
bool success = false;

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

Chilkat.Http http = new Chilkat.Http();

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

Chilkat.HttpResponse resp = new Chilkat.HttpResponse();
success = http.HttpNoBody("HEAD",url,resp);
if (success == false) {
    Debug.WriteLine(http.LastErrorText);
    return;
}

int remoteFileSize = (int) resp.ContentLength;

Debug.WriteLine("Downloading " + Convert.ToString(remoteFileSize) + " bytes...");

//  Let's download in 4 chunks.
//  (the last chunk will be whatever remains after the 1st 3 equal sized chunks)
int 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..
Chilkat.Http http1 = new Chilkat.Http();
Chilkat.Http http2 = new Chilkat.Http();
Chilkat.Http http3 = new Chilkat.Http();
Chilkat.Http http4 = new Chilkat.Http();

Chilkat.StringBuilder sbRange = new Chilkat.StringBuilder();
sbRange.SetString("bytes=<range-start>-<range-end>");
int numReplaced = sbRange.ReplaceI("<range-start>",0);
numReplaced = sbRange.ReplaceI("<range-end>",chunkSize - 1);
Debug.WriteLine(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);
Debug.WriteLine(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);
Debug.WriteLine(sbRange.GetAsString());
http3.SetRequestHeader("Range",sbRange.GetAsString());

sbRange.SetString("bytes=<range-start>-");
numReplaced = sbRange.ReplaceI("<range-start>",3 * chunkSize);
Debug.WriteLine(sbRange.GetAsString());
http4.SetRequestHeader("Range",sbRange.GetAsString());

//  Start each range download
Chilkat.Task task1 = http1.DownloadAsync(url,"qa_output/chunk1.dat");
task1.Run();

Chilkat.Task task2 = http2.DownloadAsync(url,"qa_output/chunk2.dat");
task2.Run();

Chilkat.Task task3 = http3.DownloadAsync(url,"qa_output/chunk3.dat");
task3.Run();

Chilkat.Task task4 = http4.DownloadAsync(url,"qa_output/chunk4.dat");
task4.Run();

//  Wait for the downloads to complete.
int numLive = 4;
while (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.
int numErrors = 0;
if (task1.GetResultBool() == false) {
    Debug.WriteLine(task1.ResultErrorText);
    numErrors = numErrors + 1;
}

if (task2.GetResultBool() == false) {
    Debug.WriteLine(task2.ResultErrorText);
    numErrors = numErrors + 1;
}

if (task3.GetResultBool() == false) {
    Debug.WriteLine(task3.ResultErrorText);
    numErrors = numErrors + 1;
}

if (task4.GetResultBool() == false) {
    Debug.WriteLine(task4.ResultErrorText);
    numErrors = numErrors + 1;
}

if (numErrors > 0) {

    return;
}

//  All downloads were successful.
//  Compose the file from the parts.
Chilkat.FileAccess fac = new Chilkat.FileAccess();
success = fac.ReassembleFile("qa_output","chunk","dat","qa_output/hamlet.xml");
if (success == false) {
    Debug.WriteLine(fac.LastErrorText);
}
else {
    Debug.WriteLine("Success.");
}

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

//  Compare files.
bool bSame = fac.FileContentsEqual("qa_output/hamlet.xml","qa_output/hamletRegular.xml");
Debug.WriteLine("bSame = " + Convert.ToString(bSame));