tus-js-client Resumable Upload Client
tus-js-client is a robust, pure JavaScript client library that implements the tus resumable upload protocol, enabling reliable and resilient file transfers even across network interruptions. The current stable version is 4.3.1, with the project maintaining an active release cycle that includes frequent patch updates for bug fixes (e.g., bundling issues) and minor versions for feature enhancements like expanded IETF draft support. Major version bumps, such as v4.0.0, primarily serve to update minimum Node.js environment requirements rather than introducing breaking API changes. Key differentiators include its comprehensive support for the tus protocol, cross-platform compatibility across browsers, Node.js environments (requiring Node.js >=18), and Web Workers, alongside native TypeScript type definitions for an improved developer experience. It provides a foundational solution for developers needing to handle large file uploads with progress tracking, pause/resume functionality, and error recovery.
Common errors
-
Error: Unhandled Scheme 'node:'
cause This error typically occurs in bundling environments (like Webpack or Rollup) when `tus-js-client` attempts to import Node.js built-in modules using the `node:` protocol specifier, which some bundlers do not natively support or are incorrectly configured for.fixUpgrade to tus-js-client v4.2.2 or newer, which explicitly drops the `node:` protocol for imports to resolve these bundling issues. Ensure your bundler is updated and configured correctly. -
TypeError: The 'this' context of the 'buffer' module is not allowed to be called with a non-Buffer argument
cause This error surfaced during bundling (e.g., Rollup) due to a specific interaction with how Node.js's `Buffer` type was handled and potentially polyfilled in certain environments, leading to incorrect context (`this`) being passed.fixUpdate to tus-js-client v4.3.1 or later. This version contains a patch specifically addressing this `Buffer` context issue during bundling (related to issue #748). -
ReferenceError: window is not defined
cause Although `tus-js-client` is designed to work in both browser and Node.js environments, older versions could exhibit `window` dependency issues in non-browser contexts like Web Workers or certain server-side rendering setups.fixUpgrade to tus-js-client v4.0.1 or newer. This version removed a dependency on the global `window` object, improving compatibility with Web Workers and other environments without a `window` global.
Warnings
- breaking Version 4.0.0 of tus-js-client dropped support for Node.js v14 and v16. It now requires Node.js v18 or newer.
- gotcha Bundling issues with Webpack or Rollup, specifically related to `node:` protocol imports and incorrect handling of Node.js `Buffer` context, have been reported and patched across several minor versions.
- gotcha The type definition for the `onSuccess` callback was incorrect in earlier versions of v4, potentially leading to TypeScript errors when accessing the `lastResponse` parameter.
Install
-
npm install tus-js-client -
yarn add tus-js-client -
pnpm add tus-js-client
Imports
- Upload
const Upload = require('tus-js-client').Uploadimport { Upload } from 'tus-js-client' - defaultOptions
const defaultOptions = require('tus-js-client').defaultOptionsimport { defaultOptions } from 'tus-js-client' - UploadOptions
import type { UploadOptions } from 'tus-js-client'
Quickstart
import { Upload } from 'tus-js-client';
import fs from 'fs'; // For Node.js environment
// In a browser, file would be from an <input type="file"> event
// In Node.js, you might read a file from the filesystem
const filePath = './path/to/your/file.txt';
const file = fs.createReadStream(filePath); // Or a Blob/File object in browser
const upload = new Upload(file, {
endpoint: 'https://master.tus.io/files/',
retryDelays: [0, 1000, 3000, 5000],
metadata: {
filename: 'my-document.txt',
filetype: 'text/plain'
},
headers: { // Example of custom headers
'X-Requested-With': 'XMLHttpRequest'
},
onProgress: (bytesUploaded, bytesTotal) => {
const percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
console.log(`Uploaded ${bytesUploaded} of ${bytesTotal} bytes (${percentage}%)`);
},
onSuccess: () => {
console.log('Upload finished:', upload.url);
},
onError: (error) => {
console.error('Failed to upload:', error);
if (error.originalRequest) {
console.error('Response status:', error.originalRequest.getStatus());
console.error('Response text:', error.originalRequest.getResponseText());
}
}
});
// Check if there are any previous uploads to resume
upload.findPreviousUploads().then(previousUploads => {
if (previousUploads.length) {
upload.resumeFromPreviousUpload(previousUploads[0]);
}
upload.start();
});