Resume a Partial HTTP Download Without Corrupting the File
Check Range, If-Range and Content-Range before combining a partial download with new bytes.
Keep the bytes and the version together
A connection can break after a file has partly arrived. Sending another request for the remaining bytes can save work, but appending a response blindly risks combining two different versions or adding the full file to its own beginning. First establish that the endpoint permits range requests and that you have a validator for the same representation.
For an authorized download, keep the partial file in a controlled temporary location along with the exact byte count and a strong ETag returned with that representation. Treat the URL and any credentials as sensitive. If you don't have a reliable validator, the simple safe choice is to restart rather than guess whether the source changed.
Ask for the rest of a known representation
Suppose a synthetic ten-byte file has four bytes saved locally and its strong ETag is "fixture-v1". An illustrative request and matching response are:
GET /exports/report.csv HTTP/1.1
Range: bytes=4-
If-Range: "fixture-v1"
Accept-Encoding: identity
HTTP/1.1 206 Partial Content
Content-Range: bytes 4-9/10
ETag: "fixture-v1"
Content-Length: 6
Byte positions are zero-based and inclusive: bytes 4 through 9 contain six bytes, so appending those six to the saved four makes ten. This is a local fixture, not a claim about an export provider. The HTTP specification's range section defines the headers and partial-response rules.
The If-Range condition lets a server send the range when the validator matches, or ignore the range when it doesn't. Don't use a weak ETag, identified by the W/ prefix, in If-Range. Ask for identity encoding when using raw file offsets and verify the returned encoding; transparent compression or client-side decoding can make byte counts refer to different representations.
Handle each response separately
206 Partial Content: Before appending, parse Content-Range and confirm its starting offset matches the number of bytes already saved. Check that the returned range, total length when supplied, content encoding, and received byte count agree with the expected representation. If the response includes an ETag, compare it with the stored strong validator and reject a mismatch before appending. If anything is inconsistent, keep the partial file separate and report a failure. After combining, verify the total size and a trusted checksum if the provider supplies one.
200 OK: The server may ignore Range or send the full representation when If-Range doesn't match. Don't append that response. Save it as a new full download and replace the partial file only after the new file passes your checks. A changed ETag, a changed representation, or lack of range support may explain why the server sent the full body.
416 Range Not Satisfiable: The requested start can be outside the current representation. A response may include Content-Range: bytes */10, indicating its current total size. Compare that size and validator with your partial file, then verify a trusted checksum if available. Equal lengths alone don't prove the saved bytes are correct. If you can't establish integrity, restart or report the problem rather than marking it complete.
Exercise the recovery paths
A disposable local fixture can return a six-byte 206 for the matching ETag, a complete 200 for a changed ETag, and a 416 when the requested offset is past the end. Check that only the first response is appended, that the replacement path doesn't duplicate bytes, and that the 416 path doesn't silently accept a corrupt file. The sample sequence was checked against such a local fixture; it is not a test of any vendor.
Keep retries bounded and follow the service's authorization and rate limits. If you need help designing an export workflow, ask for a scoped assessment and include a redacted response and expected file format.