xhr-upload
The reference createXhrUploadTransport transport
import { createXhrUploadTransport } from "react-mediadrop/xhr-upload";
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
import { useMediaDrop } from "react-mediadrop";
import { createXhrUploadTransport } from "react-mediadrop/xhr-upload";
const transport = createXhrUploadTransport({
endpoint: "/api/upload", // or (file) => `/api/upload/${file.id}` for a per-file URL
fields: { folder: "avatars" }, // extra multipart fields
});
const { files } = useMediaDrop({ transport, concurrency: 3, retries: 2 });
Options
| Option | Type | Default | Notes |
|---|---|---|---|
endpoint |
string | (file) => string |
— required | Computed per file, e.g. for a per-file presigned URL you already fetched. |
method |
string |
"POST" |
|
fieldName |
string |
"file" |
Ignored when formData: false. |
fields |
object | (file) => object |
— | Extra multipart fields. Ignored when formData: false. |
headers |
object | (file) => object |
— | |
withCredentials |
boolean |
false |
|
formData |
boolean |
true |
false sends the raw file body. |
isSuccessStatus |
(status) => boolean |
200–299 |
|
stallTimeoutMs |
number |
0 (disabled) |
Abort and reject if no upload progress happens for this long — a stall timeout (reset on every progress tick), not a flat total-duration one, so a large file on a slow-but-healthy connection is never falsely aborted. |
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-databy default (formData: falsesends 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/retryDelaysonuseMediaDropinstead. - It has no flat request timeout by design —
stallTimeoutMsaborts 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: falsestill 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.