Files and uploads Recommended
Make large uploads resumable
Let any upload over 100 MB, or any upload from a phone, continue from the last received byte after a dropped connection.
How to do it
Use an open protocol rather than your own. The tus protocol 1.0 is stable and has clients and servers for most languages. The IETF draft for resumable uploads (draft-ietf-httpbis-resumable-upload, version 14 in October 2026) is still a draft, not an RFC. It adds the 104 interim response and the Upload-Offset and Upload-Complete headers. Object storage multipart uploads also work, with parts of at least 5 MiB and at most 10,000 parts on S3. Retry with growing waits, such as 0, 1, 3 and 10 seconds. Set a chunk size only when a proxy limits the body size.
Example
import * as tus from 'tus-js-client';
export function uploadSiteSurvey(file, token) {
const upload = new tus.Upload(file, {
endpoint: 'https://uploads.example.com/files/',
headers: { Authorization: `Bearer ${token}` },
retryDelays: [0, 1000, 3000, 10000],
metadata: { filename: file.name, filetype: file.type },
});
upload.findPreviousUploads().then(previous => {
if (previous.length > 0) upload.resumeFromPreviousUpload(previous[0]);
upload.start();
});
}
from tusclient import client
def upload_site_survey(path: str, token: str) -> str:
tus = client.TusClient("https://uploads.example.com/files/", headers={"Authorization": f"Bearer {token}"})
uploader = tus.uploader(path, retries=5, retry_delay=3)
uploader.upload()
return uploader.url
How to check
Start a 500 MB upload, cut the network at 50 percent and reconnect. The upload finishes without sending the first half again, and the stored file's SHA-256 matches the original.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers api design playbook: https://agentwranglers.se/playbook/api-design/files-and-uploads/resumable-uploads.