File Tunnel/site
RELAY · SEOUL
All guides
GUIDE

How to Resume an Interrupted File Transfer (Without Starting Over)

Chunked streaming, per-chunk acknowledgements, and the File System Access API — how modern transfer tools survive flaky networks.

2026-05-13 · EN/KO

Half-completed transfers used to be the single most demoralizing experience of the dial-up era. We told ourselves that broadband had fixed it. It hadn't. A 30 GB transfer over a flaky hotel Wi-Fi connection, a sudden mobile network handoff, or a laptop that picks the wrong moment to suspend can still cost you an hour and force you to start over. The fix isn't faster networks. The fix is making transfers stateful, chunked, and acknowledgeable.

Why "just retry" doesn't work

A naive transfer is one giant request. The sender opens a stream, pushes bytes until done. If the stream breaks anywhere — TCP connection dropped, browser tab refreshed, OS suspended — there's no state on either side that remembers how far it got. Even if you do remember the byte offset, the server might not, or the file might have been written into an opaque object store you can't seek into.

The HTTP spec has had a partial answer for decades: range requests. Downloading a file via HTTP from a server that supports ranges, you can ask for bytes 1,000,000 to 2,000,000 specifically, which makes it possible to resume downloads. But that only works because the server has the whole file ready to seek in.

The chunked-streaming pattern

Modern real-time file transfer tools (File Tunnel included) treat the file as a sequence of fixed-size chunks: 4 MB chunks are a common choice. The protocol becomes:

  1. Sender announces a session: file name, file size, chunk size, total chunk count.
  2. Receiver opens, says "ready for chunk N." Initially N=0.
  3. Sender pushes chunk N as a binary frame with an embedded index.
  4. Receiver writes the chunk, sends "received chunk N" acknowledgement.
  5. Both sides advance, repeat until total reached.

Each chunk is an idempotent operation. If anything dies, the receiver records its last acknowledged chunk and can ask the sender to resume from there.

Acknowledging at the right level

Critical detail: the receiver should acknowledge AFTER it has committed the chunk to durable storage (or at least to its OS-level write buffer that will survive the lifetime of the process), not just after it has received the bytes. Otherwise the sender might think a chunk landed safely when in fact the receiver crashed before the bytes ever hit disk.

File Tunnel persists last-acknowledged-chunk per receiver to its database, so a receiver that disconnects and rejoins picks up from the right offset even after a process restart.

Random-access writes vs. streaming writes

How the receiver writes chunks to disk matters for resume semantics:

StreamSaver / standard download API

Bytes are appended in order. You cannot seek backwards. If the receiver disconnects halfway, you can ask the sender to start again from chunk 0, OR you must accept restart cost.

File System Access API (Chrome/Edge)

The browser obtains a file handle to a user-chosen location with random-access write permission. Each chunk can be written at its correct offset (chunk_index * chunk_size). When the receiver reconnects, it can resume by asking for the next chunk, and writes land in the right place. This is the difference between "resume from chunk 47" working and not working.

What can go wrong, and how to handle it

Browser tab closed

Sender or receiver tab closed → WebSocket drops. With last-acknowledged chunk persisted, reopening the same session and code resumes from the correct offset.

Mobile network handoff

Switching from Wi-Fi to LTE drops TCP. The reconnect logic with exponential backoff (1s, 2s, 4s, ...) re-establishes the WebSocket and resumes the chunk request loop.

Sender goes offline mid-transfer

Receiver waits in "ready for chunk N" state. When the sender reconnects with the same code, the relay forwards the receiver's outstanding request and the transfer continues.

Computer suspends to sleep

On wake, browsers reopen sockets. WebSocket reconnect kicks in. Same outcome as the network handoff case.

Chunk corruption

Per-chunk hashes (BLAKE3) let receivers detect a corrupted chunk and request a re-send for that specific chunk, without restarting the whole transfer.

Operating system considerations

macOS and Linux have stable file-write semantics; an in-progress file written via the File System Access API is persisted on close. Windows behaves similarly. Mobile OS sandboxes can be more restrictive — both iOS and Android limit long background runs of browser tabs, so on mobile a transfer is most likely to succeed if the user keeps the page in the foreground.

Best practices for users

For developers: implementing resume

If you're building this yourself, the minimum viable spec:

Get those right and your transfers survive Wi-Fi handoffs, sleep/wake cycles, and the occasional cosmic ray.

Frequently asked questions

Does Safari support resumable downloads?+

Safari does not yet implement the File System Access API, which means random-access resume is not available there. For very large files, use Chrome or Edge on desktop. Smaller transfers work fine via StreamSaver, but resuming after a disconnect may restart from chunk 0.

What chunk size is optimal?+

4 MB is a reasonable default. Larger chunks reduce protocol overhead but tie up more memory and make resume granularity coarser. Smaller chunks give finer resume but add overhead per chunk. 1-8 MB is a sensible range.

How does the receiver know which chunks to skip on resume?+

The relay persists the last-acknowledged chunk index per receiver. On reconnect, the receiver reads this value and asks the sender for the next chunk. The receiver does not need to redo any prior work.

Is the file integrity verified end to end?+

Yes. Each chunk has a BLAKE3 hash that the receiver can verify. If a chunk doesn't match, the receiver requests that single chunk again.

Can I pause a transfer intentionally and resume tomorrow?+

You can close the tab and reopen later. If the session is still within its expiry window (which you can extend to 24 hours), it picks up from where it left off.

Try it now
Open File Tunnel and send a real file. It's free up to 10 GB.