bool Updater::downloadFile(const URL& url, const File& file, int64 resume) { String headers; if (resume > 0) { headers = String("Range: bytes=") + String(resume) + String("-\r\n"); } else if (file.exists()) { if (!file.deleteFile()) { return false; } } StringPairArray responseHeaders; int statusCode; ScopedPointer<InputStream> inputStream(url.createInputStream(false, nullptr, nullptr, headers, 5000, &responseHeaders, &statusCode)); if (inputStream == nullptr) { return false; } if (resume <= 0 && statusCode != 200) { return false; } else if (resume > 0 && statusCode != 206) { return false; } ScopedPointer<FileOutputStream> outputStream(file.createOutputStream()); if (outputStream == nullptr || outputStream->failedToOpen()) { return false; } int64 length = -1; if (responseHeaders.containsKey("Content-Length")) { length = responseHeaders["Content-Length"].getLargeIntValue(); } int64 pos = 0; int64 last_pos = pos; double start_time = Time::getMillisecondCounterHiRes(); double last_time = start_time; double now; int samples[DOWNLOAD_SAMPLES]; int num_samples = 0; int next_sample = 0; int bytes_per_second; while (!inputStream->isExhausted() && !Thread::getCurrentThread()->threadShouldExit()) { char buf[0x8000]; int size = inputStream->read(buf, sizeof(buf)); outputStream->write(buf, size); pos += size; now = Time::getMillisecondCounterHiRes(); if (now - last_time >= DOWNLOAD_UPDATE_INTERVAL) { last_time = now; if (length > 0) { updater->setTaskPercent((double)pos / length); } samples[next_sample++] = (int)(pos - last_pos); last_pos = pos; if (next_sample >= DOWNLOAD_SAMPLES) { next_sample = 0; } if (num_samples < DOWNLOAD_SAMPLES) { num_samples++; } int64 accumulator = 0; for (int i = 0; i < num_samples; i++) { accumulator += samples[i]; } bytes_per_second = (int)(accumulator / (num_samples * ((double)DOWNLOAD_UPDATE_INTERVAL / 1000))); String message(String("Downloading ") + file.getFileName() + String(" at ")); if (bytes_per_second >= 1024 * 1024) { message += String((double)bytes_per_second / 1024 / 1024, 2) + String(" MB/s"); } else if (bytes_per_second >= 1024) { message += String((double)bytes_per_second / 1024, 2) + String(" KB/s"); } else { message += String(bytes_per_second) + String(" bytes/s"); } updater->setStatusText(message); } } if (pos < length) { return false; } now = Time::getMillisecondCounterHiRes(); bytes_per_second = (int)(pos / ((now - start_time) / 1000)); updater->setTaskPercent(1); String message(String("Completed download of ") + file.getFileName() + String(" at ")); if (bytes_per_second >= 1024 * 1024) { message += String((double)bytes_per_second / 1024 / 1024, 2) + String(" MB/s"); } else if (bytes_per_second >= 1024) { message += String((double)bytes_per_second / 1024, 2) + String(" KB/s"); } else { message += String(bytes_per_second) + String(" bytes/s"); } updater->setStatusText(message); return true; }