Uploads
rezo.upload() sends data to a server with real-time progress tracking. It returns a RezoUploadResponse event emitter immediately, emitting progress, completion, and error events as the upload runs in the background.
Quick Start
import { Rezo } from 'rezo';
import { readFileSync } from 'node:fs';
const rezo = new Rezo();
const fileBuffer = readFileSync('./report.pdf');
const upload = rezo.upload('https://api.example.com/upload', fileBuffer);
upload.on('progress', (p) => {
console.log(`${p.percentage.toFixed(1)}% uploaded`);
});
upload.on('finish', (info) => {
console.log('Server response:', info.response.data);
console.log('Upload speed:', (info.averageUploadSpeed / 1024).toFixed(0), 'KB/s');
});
upload.on('error', (err) => {
console.error('Upload failed:', err.message);
}); Method Signature
rezo.upload(
url: string | URL,
data: Buffer | FormData | RezoFormData | string | Record<string, any>,
options?: RezoHttpRequest
): RezoUploadResponse - url — the endpoint to upload to.
- data — the upload payload. Accepts
Buffer,FormData,RezoFormData, a string, or a plain object. - options — optional request configuration (headers, auth, proxy, timeout, etc.).
The method uses POST by default. Override via options.method if needed.
Data Types
Buffer
Upload raw binary data:
import { readFileSync } from 'node:fs';
const buffer = readFileSync('./image.png');
const upload = rezo.upload('https://api.example.com/images', buffer, {
headers: { 'Content-Type': 'image/png' }
}); RezoFormData (Multipart)
Use RezoFormData for multipart uploads with file fields:
import { RezoFormData } from 'rezo';
import { readFileSync } from 'node:fs';
const form = new RezoFormData();
form.append('title', 'Quarterly Report');
form.append('file', readFileSync('./report.pdf'), 'report.pdf');
form.append('thumbnail', readFileSync('./thumb.jpg'), 'thumb.jpg');
const upload = rezo.upload('https://api.example.com/documents', form);
upload.on('finish', (info) => {
console.log('Document ID:', info.response.data.id);
}); RezoFormData works across all environments (Node.js, Bun, Deno, browsers). It wraps the native FormData API with added convenience:
const form = new RezoFormData();
// Text fields
form.append('name', 'photo.jpg');
form.append('description', 'A sunset photo');
// File from Buffer
form.append('file', buffer, 'photo.jpg');
// File from Blob
form.append('file', new Blob([data], { type: 'image/jpeg' }), 'photo.jpg');
// Replace a field
form.set('name', 'updated-photo.jpg');
// Get the Content-Type with boundary (synchronous)
console.log(form.getContentType());
// multipart/form-data; boundary=----RezoFormBoundary... Native FormData
You can also use the native FormData directly:
const form = new FormData();
form.append('file', new Blob([buffer]), 'data.csv');
const upload = rezo.upload('https://api.example.com/import', form); String
Upload a raw string body:
const upload = rezo.upload('https://api.example.com/logs', logContent, {
headers: { 'Content-Type': 'text/plain' }
}); Object
Upload a JSON object:
const upload = rezo.upload('https://api.example.com/data', {
records: largeDataset,
timestamp: Date.now()
}); Events Reference
initiated
Emitted when the request object has been created:
upload.on('initiated', () => {
console.log('Upload request created');
}); start
Emitted when the upload begins:
upload.on('start', (info) => {
console.log('Uploading to:', info.url);
console.log('Method:', info.method);
}); headers
Emitted when the server’s response headers arrive:
upload.on('headers', (info) => {
console.log('Response status:', info.status, info.statusText);
console.log('Content-Type:', info.contentType);
}); status
Emitted with the HTTP response status:
upload.on('status', (status, statusText) => {
console.log(`Server responded: ${status} ${statusText}`);
}); cookies
Emitted with response cookies:
upload.on('cookies', (cookies) => {
cookies.forEach(c => console.log(`${c.key}=${c.value}`));
}); redirect
Emitted when a redirect is followed:
upload.on('redirect', (info) => {
console.log(`Redirect: ${info.sourceUrl} -> ${info.destinationUrl}`);
}); progress
Emitted periodically during the upload:
upload.on('progress', (progress) => {
console.log(`Uploaded: ${progress.loaded} / ${progress.total} bytes`);
console.log(`Percentage: ${progress.percentage.toFixed(1)}%`);
console.log(`Speed: ${(progress.speed / 1024).toFixed(0)} KB/s`);
console.log(`ETA: ${(progress.estimatedTime / 1000).toFixed(1)}s`);
}); Progress fields:
| Property | Type | Description |
|---|---|---|
loaded | number | Bytes uploaded so far |
total | number | Total bytes to upload |
percentage | number | 0—100 |
speed | number | Current speed in bytes/second |
averageSpeed | number | Average speed in bytes/second |
estimatedTime | number | Time remaining in milliseconds |
timestamp | number | Timestamp of this event |
finish / done
Emitted when the upload completes and the server responds:
upload.on('finish', (info) => {
// Server response
console.log('Response status:', info.response.status);
console.log('Response body:', info.response.data);
console.log('Response headers:', info.response.headers);
// Upload metadata
console.log('Upload size:', info.uploadSize, 'bytes');
console.log('File name:', info.fileName);
console.log('Final URL:', info.finalUrl);
// Timing
console.log('Total time:', info.timing.total, 'ms');
console.log('Upload time:', info.timing.upload, 'ms');
console.log('Server wait:', info.timing.waiting, 'ms');
console.log('Upload speed:', (info.averageUploadSpeed / 1024).toFixed(0), 'KB/s');
}); done is an alias for finish.
error
Emitted if the upload fails:
upload.on('error', (err) => {
console.error('Upload error:', err.code, err.message);
}); Upload Progress Bar
const form = new RezoFormData();
form.append('file', readFileSync('./backup.tar.gz'), 'backup.tar.gz');
const upload = rezo.upload('https://storage.example.com/backups', form);
upload.on('progress', (p) => {
const bar = '='.repeat(Math.floor(p.percentage / 2)).padEnd(50);
const speedKB = (p.speed / 1024).toFixed(0);
process.stdout.write(`
[${bar}] ${p.percentage.toFixed(0)}% | ${speedKB} KB/s`);
});
upload.on('finish', (info) => {
const sizeMB = (info.uploadSize / 1024 / 1024).toFixed(1);
const timeSec = (info.timing.total / 1000).toFixed(1);
console.log(`
Uploaded ${sizeMB} MB in ${timeSec}s`);
console.log('Server:', info.response.status, info.response.data);
}); With Request Options
const upload = rezo.upload('https://api.example.com/files', fileBuffer, {
headers: {
'Authorization': 'Bearer token123',
'X-Upload-Id': 'upload-abc'
},
timeout: 300_000, // 5 minute timeout for large files
proxy: 'http://proxy.example.com:8080',
maxRedirects: 3
}); Checking State
upload.isFinished(); // true after finish event
upload.url; // The upload URL
upload.fileName; // The file name (if available)
upload.status; // HTTP status code (set after response)
upload.statusText; // HTTP status text (set after response)