Skip to content
react-mediadrop
Esc
navigateopen⌘Jpreview
On this page

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-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.

Was this page helpful?