Troubleshooting

Large File Transfers: Interruptions, Resume and Integrity

By SRIFT maintainers · Published

Reviewed by SRIFT maintainers · last reviewed against the SRIFT 4.3.2 source · third-party facts checked 8 October 2026.

Short answer

Multi-gigabyte transfers usually fail because something interrupts them, not because bytes arrive corrupted: a laptop sleeps, a phone moves the tab to the background, the network changes, or the browser runs out of memory or storage. Surviving that needs resume (both sides agree on a byte offset for a file that has not changed, and remember it) and a receive path that writes to disk as data arrives.

Encryption and transport checks protect each chunk in transit, but they do not prove the finished file is the one that was sent. For files that matter, compare a SHA-256 checksum of the original and the copy.

Main failure mode
Interruption, not corruption
Resume needs
Byte-offset acknowledgements, stable file identity, persisted state
Browser receive paths
Stream to Downloads, private file storage, or memory
Final check
SHA-256 of both copies, compared out of band

Why big transfers fail, and how to verify what arrived. To simply send a large file, see send large files free, no signup.

Why large transfers fail

Size turns rare events into likely ones. At 10 MB/s, a 50 GB file takes about 5,000 seconds, roughly 83 minutes, and every interruption in that window has to be survived. The common ones:

Common causes of failed large transfers and how to prevent each.
CauseWhat happensPrevention
Sleep or lock screenThe OS suspends networking; connections time out on both ends.Plug in, disable sleep for the duration, keep the screen on for phones.
Mobile background limitsiOS and Android suspend or restrict pages that are not in the foreground.Keep the browser in the foreground; prefer a desktop for very large files.
Network changeMoving from Wi-Fi to cellular, a VPN reconnect or a new DHCP lease changes the address; WebRTC paths and TCP connections break.Stay on one stable, preferably wired, network; disable VPN auto-reconnect.
Tab memoryCode that buffers the file in memory grows until the tab is killed.Use a tool that writes to disk as it receives.
Storage quotaBrowser-private storage has a per-origin quota; writes beyond it fail.Check free space; use a path that saves directly to Downloads.
Download semanticsA file assembled by script appears only when complete; a streamed one can be left half-written if the page dies.Know which path your browser uses (next sections).

Storage quotas vary by browser. MDN's storage quota documentation gives Chromium browsers up to 60% of total disk per origin, while Firefox in its default best-effort mode allows the smaller of 10% of the disk or a 10 GiB limit shared by the whole site. A page can ask with navigator.storage.estimate(), and the numbers are estimates, not promises: quotas are computed from total disk size, so the free space can run out first.

What resume really requires

“Resumable” is often claimed and rarely defined. A transfer can continue after an interruption only if four things hold:

  1. Byte-offset acknowledgements. The receiver acknowledges bytes it has written, not merely received, so the offset it reports after a crash is true. Chunked transfers usually acknowledge chunk indexes, which map to byte offsets.
  2. Stable file identity. Both sides must know the bytes after the offset belong to the same file. If the source changed (same name, new contents), continuing would splice two versions together. HTTP solves this with validators such as ETag and If-Range on range requests (RFC 9110); a custom protocol needs a file ID tied to size, modification time or a hash.
  3. Persisted state. The offset and the partial data must survive the event that interrupted the transfer. Memory does not survive a page reload; IndexedDB, browser file storage or a partial file on disk does.
  4. A transport that can start mid-file. HTTP range requests, or a protocol message meaning “send from byte N”.
Resuming a transfer from the last acknowledged byteA bar represents the file from byte zero to the end. The first part is acknowledged and written to disk, the next part was in flight when the connection dropped, and the rest was never sent. After reconnecting, the sender restarts from the acknowledged offset, so in-flight chunks are sent again and acknowledged data is not.Before the dropacknowledged and writtenin flightnot sent yetpersisted offsetreceiver reports it on reconnectAfter reconnectingkept, not re-sentsender continues from the offset
Resume continues from the receiver's persisted offset: chunks that were in flight are sent again, acknowledged ones are not.

Authenticated encryption helps here too. When each chunk is sealed with AES-GCM and its index is part of the associated data, a chunk replayed at the wrong position fails to decrypt instead of silently corrupting the file; how AES-256-GCM works explains why.

How a browser can receive a very large file

A web page cannot simply open a file in the Downloads folder and append to it. There are three main ways to receive a large file, with different limits:

Receiving strategies for large files in a browser.
StrategyHow it worksLimits
Service worker streamingThe page hands chunks to a service worker, which answers a download request with a streamed response. The file appears in Downloads while it arrives and needs its size on disk once.Needs the page and worker alive. Not reliable on iOS and iPadOS, Firefox for Android or Android WebViews. Firefox cannot cleanly abort a streamed download: it stays "in progress", and closing the stream early would make a truncated file look complete.
Origin private file system (OPFS)Chunks are written to browser-private storage, ideally from a worker with a sync access handle, then saved to Downloads when complete.Bounded by the origin's storage quota; the save at the end briefly needs room for a second copy.
MemoryChunks are kept in memory and joined into a Blob at the end.Only for files well below the device's free memory.

Chromium browsers also offer the File System Access API (showSaveFilePicker), which lets the user pick a destination file the page can write to directly. On a phone, the practical advice is simpler: for files in the tens of gigabytes, receive on a desktop browser or with a command-line client.

How SRIFT handles interruptions

Browser sessions

  • Byte-position resume within a transfer. If a direct WebRTC connection fails mid-transfer, the encrypted relay continues from the bytes the receiver already holds.
  • Survives a page reload. Relay acknowledgements are stored in IndexedDB, so a reloaded page continues the same relay transfer. In Chrome and Edge, a receiving tab closed and reopened within minutes continues the same download, because the service worker keeps it alive.
  • Streams into Downloads where that is reliable, otherwise writes to the origin private file system and saves when complete, with memory as the last resort. Streaming is not used on iOS and iPadOS, Firefox for Android or Android WebViews. The 4.3.2 changelog records a 20 GB browser-to-browser transfer with about 100 MB of page memory.
  • Ends cleanly when the sender is gone. The receiver ends a transfer 60 seconds after the sender leaves the session, or after 11 minutes without any data, and cleans up a streamed download. A send after that is a new transfer.
  • Keeps the device awake where it can, by requesting a screen wake lock during transfers on browsers that support it. It cannot stop someone closing a laptop lid.

Quick-share links and the CLI

Quick-share serves a file from the sender's machine through an HTTPS link. A link refuses to serve a file that changed after the link was created, which gives it a stable identity. srift get writes to a partial file, resumes with HTTP range requests and retries with backoff. The server closes a download whose bytes stop flowing for 60 seconds so the client can resume; for single-use and download-limited links, the resume must come within one hour of the last range request.

Receiving with the CLI
srift get "https://srift.app/d/<token>#k=<key>" -o ./big.iso
# several links in parallel (default 4, maximum 16)
srift get <link1> <link2> <link3> --concurrency 8 -o ./downloads/

The send large files page covers the browser flow step by step.

Verifying the file that arrived

Transport security checks each piece in transit: TLS and DTLS authenticate every record, and AES-GCM tags authenticate every sealed chunk. What they do not cover is the finished file: a bug in reassembly, a write error on the receiving disk, a truncated download that looks complete, or simply the wrong file sent. Only hashing the complete file on both ends answers “is this the same file?”.

Compute SHA-256 (specified in FIPS 180-4) on the sender before sending and on the receiver after:

Linux
sha256sum big.iso > big.iso.sha256   # sender
sha256sum -c big.iso.sha256          # receiver: prints "big.iso: OK"
macOS
shasum -a 256 big.iso
shasum -a 256 -c big.iso.sha256
Windows PowerShell
Get-FileHash .\big.iso            # SHA256 is the default algorithm
(Get-FileHash .\big.iso).Hash -eq "<expected hash>"

Send the checksum through a different channel from the file, such as a chat message, a ticket or a signed release note. A checksum that travels with the file only detects accidents; one that travels separately also detects tampering on the file's path.

Checklist before sending a 50 GB file

  1. Estimate the time from the sender's upload speed: size divided by rate. If it runs to hours, plan around it (see why P2P transfers are slow).
  2. Check free space on the receiver: at least the file size, and twice that if the browser stores the file privately before saving it.
  3. Choose the receiving side carefully: a desktop Chromium browser that streams to Downloads, or a command-line client. Avoid phones and in-app browsers for files this size.
  4. Power and sleep: plug both machines in and prevent sleep for the duration.
  5. Network: use a wired or stable connection, stay on one network, and turn off VPN auto-reconnect.
  6. Hash first: compute SHA-256 on the sender and send it separately.
  7. Test with a small file on the same two devices and networks.
  8. Consider splitting the data into several files of a few gigabytes, so an unrecoverable failure costs one part rather than everything.
Keeping a machine awake while a command runs
caffeinate -dims srift quick-share big.iso --wait      # macOS
systemd-inhibit --what=sleep:idle srift quick-share big.iso --wait   # Linux
powercfg /change standby-timeout-ac 0                 # Windows: no sleep on AC power

Frequently asked questions

Can a browser receive a file larger than its memory?

Yes, if it writes to disk as data arrives: by streaming the file into the download manager through a service worker, or by writing to the origin private file system. A design that keeps the whole file in memory cannot.

Does TLS or end-to-end encryption guarantee the whole file is intact?

They guarantee that each record or chunk was not altered in transit. They do not prove that every chunk arrived, was written correctly, and belongs to the file you expected. A SHA-256 comparison of the complete file does.

Why does Firefox show a failed streamed download as still in progress?

Firefox cannot mark a script-streamed download as failed. Closing the stream would make it look complete even if it is cut off, so a careful implementation leaves it open, and the entry stays in progress until removed.

References

  1. RFC 9110: HTTP Semantics (range requests) (IETF)
  2. Storage quotas and eviction criteria (MDN)
  3. Origin private file system (MDN)
  4. Service Worker API (MDN)
  5. FIPS 180-4: Secure Hash Standard (SHS) (NIST)
  6. Get-FileHash (Microsoft)

Try a direct transfer

Open a session in one browser, join it from another device, and send a file. No account, nothing to install on either side.