A framework-agnostic JavaScript file uploader library with queue management, progress tracking, abort support, and file validation.
- Framework-agnostic — Works in browsers and Node.js
- Dual module support — ESM and CommonJS
- Queue management — Add multiple files and upload them in sequence or parallel
- Progress tracking — Real-time upload progress via events
- Abort support — Cancel individual uploads or all at once
- File validation — Built-in size and MIME type validation with glob patterns
- Custom validators — Support for async validation functions
- Concurrency control — Limit simultaneous uploads with
maxConcurrent - Retry logic — Automatic retry for failed uploads
- Event-driven — Subscribe to
add,progress,success,error,remove,retryevents - TypeScript — Full TypeScript support with type definitions
# Using bun
bun add @designbycode/uploader-core
# Using npm
npm install @designbycode/uploader-core
# Using pnpm
pnpm add @designbycode/uploader-coreimport { Uploader } from "@designbycode/uploader-core";
const uploader = new Uploader({
process: async (file, { signal, onProgress }) => {
const formData = new FormData();
formData.append("file", file);
const response = await fetch("/api/upload", {
method: "POST",
body: formData,
signal,
});
return { serverId: response.json().id };
},
});
// Add files and upload
const input = document.querySelector('input[type="file"]');
input.addEventListener("change", async () => {
const added = await uploader.addFiles(Array.from(input.files));
uploader.uploadAll();
});
// Listen for events
uploader.on("progress", (file) => {
console.log(`${file.file.name}: ${file.progress}%`);
});
uploader.on("success", (file) => {
console.log(`${file.file.name} uploaded successfully`);
});Creates a new uploader instance.
const uploader = new Uploader({
autoUpload: false, // Automatically upload files when added
maxConcurrent: 2, // Limit simultaneous uploads
validation: {
// File validation rules
maxSize: 10 * 1024 * 1024, // 10MB
acceptedMimeTypes: ["image/png", "image/jpeg"],
},
process: async (file, { signal, onProgress }) => {
// Your upload logic here
return { serverId: "file-id" };
},
});| Option | Type | Description |
|---|---|---|
autoUpload |
boolean |
Automatically upload files when added |
maxConcurrent |
number |
Maximum simultaneous uploads (default: unlimited) |
validation |
ValidationRule | FileValidator |
File validation rules or custom validator |
maxRetries |
number |
Maximum retry attempts for failed uploads |
retryDelay |
number |
Delay between retries in ms (default: 1000) |
process |
ProcessFn |
Function to handle the actual upload |
revert |
RevertFn |
Function to undo upload (e.g., delete from server) |
onAdd |
Callback |
Called when a file is added |
onProgress |
Callback |
Called when upload progress updates |
onSuccess |
Callback |
Called when upload succeeds |
onError |
Callback |
Called when upload fails |
onRemove |
Callback |
Called when a file is removed |
onRetry |
Callback |
Called when upload is retried |
onValidationError |
Callback |
Called when validation fails |
Add files to the upload queue. Returns the added UploadFile objects.
const added = await uploader.addFiles([file1, file2, file3]);
console.log(`Added ${added.length} files`);Upload a single file by its ID.
await uploader.uploadFile("file-uuid");Upload all queued files.
uploader.uploadAll();Cancel an in-progress upload.
uploader.cancelFile("file-uuid");Cancel all in-progress uploads.
uploader.cancelAll();Remove a file from the queue. Calls revert() if the file was uploaded.
await uploader.removeFile("file-uuid");Get all files in the queue.
const files = uploader.getFiles();
files.forEach((f) => console.log(f.file.name, f.status));Get a single file by ID.
const file = uploader.getFile("file-uuid");Get a single file by its server ID (after upload).
const file = uploader.getFileByServerId("server-123");Clear all files from the queue.
uploader.clear();Subscribe to an event. Returns an unsubscribe function.
const unsubscribe = uploader.on("success", (file) => {
console.log(`${file.file.name} uploaded!`);
});
// Later, unsubscribe
unsubscribe();Subscribe to an event for a single execution.
uploader.once("success", (file) => {
console.log("First upload completed!");
});Unsubscribe from an event.
const handler = (file) => console.log(file.file.name);
uploader.on("success", handler);
uploader.off("success", handler);| Event | Payload | Description |
|---|---|---|
add |
UploadFile |
File added to queue |
progress |
UploadFile |
Upload progress updated |
success |
UploadFile |
Upload completed |
error |
UploadFile |
Upload failed |
remove |
UploadFile |
File removed from queue |
retry |
{ file: UploadFile, attempt: number } |
Upload being retried |
const uploader = new Uploader({
validation: {
maxSize: 5 * 1024 * 1024, // 5MB max
minSize: 1000, // 1KB min
acceptedMimeTypes: ["image/png", "image/jpeg", "image/gif"],
rejectedMimeTypes: ["application/exe"],
},
process: async (file, { signal, onProgress }) => {
// ...
},
});
uploader.on("validationError", (file, error) => {
console.error(`${file.name} rejected: ${error}`);
});const uploader = new Uploader({
validation: async (file) => {
// Check file name
if (!file.name.match(/^[a-zA-Z0-9-_]+\.[a-z]+$/)) {
return { valid: false, error: "Invalid file name format" };
}
// Async validation (e.g., check against API)
const isAllowed = await checkFileAllowed(file);
if (!isAllowed) {
return { valid: false, error: "File not allowed" };
}
return { valid: true };
},
});Limit simultaneous uploads:
const uploader = new Uploader({
maxConcurrent: 2, // Only 2 uploads at a time
process: async (file, { signal, onProgress }) => {
// ...
},
});
// Add 10 files, only 2 will upload at once
await uploader.addFiles(files);
uploader.uploadAll();Automatically retry failed uploads:
const uploader = new Uploader({
maxRetries: 3, // Retry up to 3 times
retryDelay: 1000, // Wait 1 second between retries
process: async (file, { signal, onProgress }) => {
// ...
},
});
uploader.on("retry", ({ file, attempt }) => {
console.log(`Retrying ${file.file.name} (attempt ${attempt})`);
});interface UploadFile {
id: string;
file: File;
status: "idle" | "queued" | "uploading" | "success" | "error" | "cancelled";
progress: number;
serverId?: string;
error?: string;
}type UploadStatus =
| "idle"
| "queued"
| "uploading"
| "success"
| "error"
| "cancelled";interface ValidationRule {
maxSize?: number;
minSize?: number;
acceptedMimeTypes?: string[];
rejectedMimeTypes?: string[];
}MIT