FrontendPro

127Build a resumable upload client handling network interruption and server reconciliation

hardAbout 75 minutesCodinguploadsresumablenetworktus

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 with status: 404 if the session expired.
  • api.uploadRange(uploadId, offset, blob) appends blob at offset and resolves { receivedBytes }. It rejects with status: 409 if offset is not exactly the server's current size.
  • api.complete(uploadId).

Requirements:

  • Remember the uploadId in storage (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 retries consecutive failures (reject with the last error), keeping the stored uploadId so a later start() can resume.
  • If the session expired (getStatus rejects 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 later start() continues.
  • When everything is sent, call complete, remove the stored id and resolve { status: "complete", uploadId }. Report onProgress(receivedBytes / size) after each chunk.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

solution.jsJavaScript

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.

All 150 answersOne payment, yours forever