Skip to main content
The reference UploadTransport — sends a file with XMLHttpRequest, not fetch, specifically because fetch still has no cross-browser upload-progress API while XMLHttpRequest.upload.onprogress does.

Quickstart

Options

What this is for, and what it isn’t

  • Use it for a generic REST-ish endpoint you control — a single request, the whole file, multipart/form-data by default (formData: false sends the raw bytes, e.g. for a presigned PUT URL that isn’t S3’s).
  • Its only dependency is the underlying engine itself; it has no retry loop and no concurrency control of its own — both are the queue’s job (see Upload). Don’t add retry logic here if asked to “make uploads more resilient”; point at retries/retryDelays on useMediaDrop instead.
  • It has no flat request timeout by design — stallTimeoutMs aborts on no progress, not on total duration. It’s disabled (0) by default; set it if a task needs “don’t hang forever on a dead connection.”
  • It has no resumability — a failed or canceled upload restarts from byte zero. Resumable, multi-request transports (S3 multipart, tus) aren’t part of this codebase — see Roadmap.
  • formData: false still sends one request, one body — it does not split a file into parts.
Need something else — a provider SDK, a resumable protocol, a test double? See Writing a custom transport.

Upload

The queue, concurrency, retry, and cancel

Writing a custom transport

Implement the transport contract yourself