127Build a resumable upload client handling network interruption and server reconciliation
Problem
A user uploads a 1 GB video on hotel Wi-Fi. The connection drops at 63%, and later they close the laptop. When they come back, the upload should continue from where the server stopped, not start over and not send any byte twice.
Implement createResumableUpload(file, { api, chunkSize, storage, retries = 3, retryDelay = (n) => 200 * 2 ** n, sleep, onProgress = () => {} }) returning { start(), pause() }. The server API (similar to the tus protocol):
api.createSession({ name, size })resolves{ uploadId }.api.getStatus(uploadId)resolves{ receivedBytes }, or rejects withstatus: 404if the session expired.api.uploadRange(uploadId, offset, blob)appendsblobatoffsetand resolves{ receivedBytes }. It rejects withstatus: 409ifoffsetis not exactly the server's current size.api.complete(uploadId).
Requirements:
- Remember the
uploadIdinstorage(getItem/setItem/removeItem) under a key derived from the file (upload:{name}:{size}:{lastModified}), so a reload resumes the same session. - Before sending, ask the server how much it has (
getStatus). The server's offset is the truth. - Send chunks sequentially from that offset. After any failure, wait (
sleep(retryDelay(n))), ask the server for its offset again, and continue from there. This handles responses lost after the server already stored the chunk. - Give up after
retriesconsecutive failures (reject with the last error), keeping the storeduploadIdso a laterstart()can resume. - If the session expired (
getStatusrejects with 404), create a new session and start from 0. pause()stops after the current chunk;start()resolves with{ status: "paused", offset }then, and a laterstart()continues.- When everything is sent, call
complete, remove the stored id and resolve{ status: "complete", uploadId }. ReportonProgress(receivedBytes / size)after each chunk.
Try it yourself
Write your solution, run it, then submit to check it against the tests.
Press Run or ⌘ Enter to execute your code.
Step-by-step
name + size + lastModified is a cheap fingerprint that survives reloads (the browser gives you a new File object each time the user picks it). Use it as the storage key for the upload id.
Unlock the full solution
What's inside
- Step-by-step
- Approach
- Solution
- Complexity
- Edge cases
- Follow-up questions
- Tests
Includes 2 code listings, 5 edge cases, 4 follow-up questions.
One-time payment by UPI, card or net banking. Launch price.