Uploads & Downloads
Upload FormData, File, Blob and binary bodies with @mrzr/api-client, keep long uploads from failing on token expiry, and download files as a Blob.
Uploading
Pass the body as-is. The client doesn't JSON-encode it and picks the right Content-Type:
const form = new FormData();
form.append("avatar", file);
await api.post("/me/avatar", form); // multipart, boundary set by the browser
await api.put("/files/1", file); // File or Blob: sent as raw bytes
await api.post("/raw", new Uint8Array([1, 2, 3]));| Body | Sent as |
|---|---|
| Plain object or array | JSON |
FormData | multipart/form-data |
File, Blob | Raw bytes with the file's type |
ArrayBuffer, typed arrays | Raw bytes |
URLSearchParams | application/x-www-form-urlencoded |
string | As-is, with Content-Type: application/json unless you set another |
Long uploads
The default timeout is 30 s. Raise it for big files:
await api.post("/upload", form, { timeout: 10 * 60_000 });If the token expires mid-upload, the server answers 401 and the client refreshes and re-sends the file automatically. To avoid uploading twice, refresh before starting when the token won't last the whole upload:
await api.post("/upload", form, { uploadSkewMs: 10 * 60_000 });Streams
A ReadableStream body works only with worker: false, because a stream can't be passed into a Web Worker. It also can't be replayed after a 401, so combine it with uploadSkewMs.
Downloading files
Non-text responses (images, PDFs, zip files) resolve as a Blob:
const { data } = await api.get<Blob>("/reports/42.pdf");
const url = URL.createObjectURL(data!);Pass responseType: "blob" or "arrayBuffer" to force a format.
Upload progress isn't available: fetch doesn't report it. Use XMLHttpRequest for a progress bar.
Cancellation
Cancel in-flight requests when the user leaves a page, closes a modal or types the next search keystroke. Cancel by key, group, URL pattern or scope.
Web Worker & Tabs
How @mrzr/api-client keeps access tokens inside a Web Worker away from XSS, when it falls back to the main thread, and how tabs share login and logout.