Recipes: media and files
Photos, videos and documents are where offline queues earn their keep: large, slow, and easy to lose. These recipes cover progress, pipelines, chunking and cleanup.
First, make the file permanent
Image pickers and cameras often return a temporary file that the system may delete before the upload runs. Copy it into your app's own storage before you enqueue, and put that path in the payload.
Upload with progress, cancel and retry
fetch in React Native does not report upload progress. Use XMLHttpRequest.
The list with progress bar, retry and cancel buttons is on React hooks.
Compress, then upload
Two steps, two jobs. Compression needs no network, so it runs immediately, offline. Upload waits for connectivity.
- The user sees "Saved" immediately; compression happens in the background.
- If the app dies between the stages, compression runs again or the upload is already saved: each step is its own persisted job.
- Keep each stage idempotent:
idempotent: trueon delete, and compressing an already compressed file must be harmless.
A whole album, politely
Two-step upload with a signed URL
Get a pre-signed URL from your API, then PUT the file to storage (S3, GCS, Azure Blob).
Step 1 uses the job id as idempotency key, so a retry returns the same object key and does not create orphans.
Chunked uploads
For files too large for one request, one job per chunk, plus a finalize job when all chunks are in. Chunk ids are deterministic, so re-enqueueing is harmless, and progress survives restarts.
With limits: { uploadChunk: { concurrency: 3 } } you get three chunks in
parallel, each retried independently on its own.
Resumable upload in one job (generator)
An async function* handler is a natural fit for sequential chunking: every
yield is a point where cancellation takes effect, and a retry resumes from where
the server says it left off.
A thrown error makes the queue run the generator again from the top, but
getServerOffset makes the next run skip what is already uploaded.
Big videos: native background upload
For videos, prefer the OS uploader so the transfer continues when the user leaves the app.
QueueKit tracks it with ctx.detach(). The full walkthrough, including reattaching
after a restart, is on Background and native tasks.
Downloads and prefetching
A low priority keeps prefetching from delaying user actions, and ttlMs drops
requests the user no longer needs (they scrolled past). To prefetch only on Wi-Fi, use
a separate queue with a Wi-Fi-only monitor.
Clean up temp files
Delete the local copy only when you are sure it is no longer needed: after success, or after the user discards a failed job.
Also sweep your upload directory at startup for files with no matching job, to catch leftovers from crashes: