Robust Large-File Download
Purpose
Download multi-GB files reliably over flaky or throttled connections by combining three techniques:
1. HTTP Range chunking — split the file into chunks; any interruption only loses the current chunk, and the rest resumes.
2. Multi-connection parallelism — download several chunks at once to defeat per-connection bandwidth caps (a single connection often crawls at ~200 KB/s while the link is much faster).
3. Detached Scheduled Task — run the download under Windows Task Scheduler so closing WorkBuddy does not kill it.
When to use
- User reports a large download "keeps failing", stalls, or cannot resume.
- Downloading research datasets (Zenodo, OpenML, etc.) larger than ~1 GB.
- A single browser/curl download is too slow or unreliable.
Workflow
- Verify Range support before writing anything:
curl -s -r 0-0 -D hdr.txt -o /dev/null <URL>then inspecthdr.txtforaccept-ranges: bytesandcontent-range: bytes 0-0/<TOTAL>. A206response confirms chunking; the total size comes from the header. - Check disk space: free space must exceed file size + one chunk.
- Run the bundled downloader
scripts/download_chunked.py— it auto-detects total size, downloads in 200 MB chunks, 4 parallel workers, resumes via.ok{i}markers, and optionally verifies MD5:
python scripts/download_chunked.py --url <URL> --out <path> [--md5 <md5>] [--workers 4] [--chunk 209715200] - Run it detached so it survives app close — wrap in a Windows Scheduled Task:
schtasks /create /tn <TaskName> /tr "\"<python>\" \"<script>\" --url <URL> --out <path>" /sc once /st 00:00 /f
thenschtasks /run /tn <TaskName>.
- Do NOT use a.batwrapper with non-ASCII paths (encoding garbles filenames). Passpython + scriptdirectly in/tr. - Monitor by tailing
<out>.progress.log, or measure aggregate speed = sum of all<out>.cNtemp sizes over a 30s window. - Resume is automatic: re-run the same command; completed chunks are skipped via markers.
- Stop:
schtasks /end /tn <TaskName>+taskkill /F /PID <pid>.
Key gotchas
- Per-connection throttle: if one connection crawls (~200 KB/s) but the link is faster, parallelism (4 workers) often yields 5–9× speedup. Measure sequential speed first, then switch to parallel if slow.
- Rate limits: some hosts (e.g. Zenodo) cap requests/min (~133). Large chunks (200 MB) keep request count low; sequential with 1s sleeps stays far under the cap.
- Resumability across restarts: never truncate the output on restart — open with
O_RDWR|O_CREATandos.pwriteeach chunk at its own offset. Track completion with per-chunk marker files (not a single offset) so out-of-order parallel completion is safe. - Safe-delete noise: a
rmof an in-use temp file may emit trash-fallback errors — harmless; the next run overwrites/removes it. - Proxy environments:
curlhonorshttp_proxy/https_proxyand Range through proxies; prefer acurlsubprocess overurllibto avoid proxy surprises.
Reference
Bundled scripts/download_chunked.py is the complete, parameterized, production-used implementation.