High-performance file uploads with Web Streams API, automatic fallbacks, and resumable uploads. < 10 kB gzipped, zero dependencies, 100% TypeScript.
| Method | HTTP | Memory | Progress | Resumable | Legacy |
|---|---|---|---|---|---|
| Fetch Stream | 1 | O(1) ✅ | ❌ | ❌ | |
| Fetch Chunked | N | O(chunk) ✅ | ✅ | ✅ | ❌ |
| XHR Chunked | N | O(chunk) ✅ | ✅ | ✅ | ✅ |
Auto-selects the best method for your browser.
npm install @universal-uploader/core
# or use @universal-uploader/react for React hook version
yarn add @universal-uploader/core
pnpm add @universal-uploader/coreNPM Packages:
import upload from '@universal-uploader/core';
const { result, actions } = await upload({
url: '/api/upload',
file,
options: {
method: 'auto',
onProgress: ({ percentage }) => console.log(`${percentage}%`),
onRetry: () => console.log('Retrying...'),
retryCount: 3,
},
});import { useState } from 'react';
import { useUniversalUpload } from '@universal-uploader/react';
export const Upload = () => {
const [progress, setProgress] = useState(0);
const { upload, pause, resume, abort, refresh, status, uploadMethod, result, error } = useUniversalUpload({
url: '/api/upload',
options: {
method: 'auto',
retryCount: 3,
onProgress: (p) => setProgress(Math.round(p.percentage))
}
});
return (
<div>
<input type="file" onChange={(e) => e.target.files && upload(e.target.files[0])} />
<progress value={progress} max={100} />
<p>Status: {status}</p>
<p>Method: {uploadMethod ?? 'pending'}</p>
{status === 'uploading' && (
<>
<button onClick={pause}>Pause</button>
<button onClick={abort}>Abort</button>
</>
)}
{status === 'paused' && <button onClick={resume}>Resume</button>}
{(status === 'error' || status === 'aborted') && (
<button onClick={refresh}>Restart</button>
)}
{error && <p style={{ color: 'red' }}>{error.message}</p>}
</div>
);
};- ✅ Constant Memory - Web Streams keeps memory O(1) even for multi-GB files
- ✅ Smart Fallback - Auto-detects Fetch capabilities, falls back to XHR
- ✅ Resumable - Pause and resume with chunked methods
- ✅ Progress - Detailed callbacks for all methods
- ✅ Retry - Automatic exponential backoff (
retryCount,retryDelay,onRetry) - ✅ Controls -
abort(),pause(),resume(),refresh()(retrydeprecated in React hook) - ✅ Type-Safe - Full TypeScript support
- ✅ Tiny - < 10 kB gzipped, zero dependencies
📚 Interactive Guide & Documentation - Full documentation with examples (한국어, English)
const { result, actions } = await upload({ url, file, options });
const { abort, pause, resume, refresh } = actions;
pause(); // Status: "paused" (resumable)
resume(); // Continue from offset
abort(); // Status: "aborted" (terminal)
refresh(); // Full restart from initial optionsinterface UploadOptions {
method?: 'stream' | 'stream chunked' | 'xhr chunked' | 'auto';
chunkSize?: number; // Default: 512KB
retryCount?: number; // Default: 3
retryDelay?: number | ((attempt: number) => number);
customHeaders?: Record<string, string>;
withCredentials?: boolean;
offset?: number;
onProgress?: (p: { loaded: number; total: number; percentage: number }) => void;
onComplete?: (response?: Response) => void; // Response for 'stream'/'stream chunked'; undefined for 'xhr chunked' & empty files
onError?: (error: Error) => void;
onRetry?: () => void;
onPause?: () => void;
onResume?: () => void;
onAbort?: (error: DOMException) => void;
throwOnError?: boolean | ((error: unknown) => boolean); // Default: false
}| Browser | Support |
|---|---|
| Chrome / Edge | ✅ Fetch Stream |
| Firefox | ✅ Fetch Stream |
| Safari | ✅ XHR Fallback |
| IE 11+ | ✅ XHR Fallback |
- Online Documentation - Interactive guide (한국어, English)
- @universal-uploader/core - Core upload engine API
- @universal-uploader/react - React Hook guide
- Demo Source - Demo app code
MIT