Unicode C++
Unicode 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 Unicode C++ Downloads
#include <CkHttpW.h>
#include <CkHttpResponseW.h>
#include <CkStringBuilderW.h>
#include <CkTaskW.h>
#include <CkFileAccessW.h>
void ChilkatSample(void)
{
bool success = false;
// This requires the Chilkat API to have been previously unlocked.
// See Global Unlock Sample for sample code.
CkHttpW http;
// First get the size of the file to be downloaded.
const wchar_t *url = L"https://www.chilkatsoft.com/hamlet.xml";
CkHttpResponseW resp;
success = http.HttpNoBody(L"HEAD",url,resp);
if (success == false) {
wprintf(L"%s\n",http.lastErrorText());
return;
}
int remoteFileSize = resp.get_ContentLength();
wprintf(L"Downloading %d bytes...\n",remoteFileSize);
// 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..
CkHttpW http1;
CkHttpW http2;
CkHttpW http3;
CkHttpW http4;
CkStringBuilderW sbRange;
sbRange.SetString(L"bytes=<range-start>-<range-end>");
int numReplaced = sbRange.ReplaceI(L"<range-start>",0);
numReplaced = sbRange.ReplaceI(L"<range-end>",chunkSize - 1);
wprintf(L"%s\n",sbRange.getAsString());
http1.SetRequestHeader(L"Range",sbRange.getAsString());
sbRange.SetString(L"bytes=<range-start>-<range-end>");
numReplaced = sbRange.ReplaceI(L"<range-start>",chunkSize);
numReplaced = sbRange.ReplaceI(L"<range-end>",2 * chunkSize - 1);
wprintf(L"%s\n",sbRange.getAsString());
http2.SetRequestHeader(L"Range",sbRange.getAsString());
sbRange.SetString(L"bytes=<range-start>-<range-end>");
numReplaced = sbRange.ReplaceI(L"<range-start>",2 * chunkSize);
numReplaced = sbRange.ReplaceI(L"<range-end>",3 * chunkSize - 1);
wprintf(L"%s\n",sbRange.getAsString());
http3.SetRequestHeader(L"Range",sbRange.getAsString());
sbRange.SetString(L"bytes=<range-start>-");
numReplaced = sbRange.ReplaceI(L"<range-start>",3 * chunkSize);
wprintf(L"%s\n",sbRange.getAsString());
http4.SetRequestHeader(L"Range",sbRange.getAsString());
// Start each range download
CkTaskW *task1 = http1.DownloadAsync(url,L"qa_output/chunk1.dat");
task1->Run();
CkTaskW *task2 = http2.DownloadAsync(url,L"qa_output/chunk2.dat");
task2->Run();
CkTaskW *task3 = http3.DownloadAsync(url,L"qa_output/chunk3.dat");
task3->Run();
CkTaskW *task4 = http4.DownloadAsync(url,L"qa_output/chunk4.dat");
task4->Run();
// Wait for the downloads to complete.
int numLive = 4;
while (numLive > 0) {
numLive = 0;
if (task1->get_Live() == true) {
numLive = numLive + 1;
}
if (task2->get_Live() == true) {
numLive = numLive + 1;
}
if (task3->get_Live() == true) {
numLive = numLive + 1;
}
if (task4->get_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) {
wprintf(L"%s\n",task1->resultErrorText());
numErrors = numErrors + 1;
}
if (task2->GetResultBool() == false) {
wprintf(L"%s\n",task2->resultErrorText());
numErrors = numErrors + 1;
}
if (task3->GetResultBool() == false) {
wprintf(L"%s\n",task3->resultErrorText());
numErrors = numErrors + 1;
}
if (task4->GetResultBool() == false) {
wprintf(L"%s\n",task4->resultErrorText());
numErrors = numErrors + 1;
}
if (numErrors > 0) {
delete task1;
delete task2;
delete task3;
delete task4;
return;
}
// All downloads were successful.
// Compose the file from the parts.
CkFileAccessW fac;
success = fac.ReassembleFile(L"qa_output",L"chunk",L"dat",L"qa_output/hamlet.xml");
if (success == false) {
wprintf(L"%s\n",fac.lastErrorText());
}
else {
wprintf(L"Success.\n");
}
delete task1;
delete task2;
delete task3;
delete task4;
// Let's download in the regular way, and then compare files..
success = http.Download(url,L"qa_output/hamletRegular.xml");
// Compare files.
bool bSame = fac.FileContentsEqual(L"qa_output/hamlet.xml",L"qa_output/hamletRegular.xml");
wprintf(L"bSame = %d\n",bSame);
}