Elegant & feature rich browser / node HTTP with a fluent API
—
Multipart form data support for file uploads and form submissions with comprehensive options for handling files, streams, and buffers.
Methods for attaching files to multipart requests.
/**
* Attach a file to the request as multipart/form-data
* @param {string} field - Form field name
* @param {string|Buffer|Stream} file - File path, Buffer, or Stream
* @param {string|object} [options] - Filename string or options object
* @param {string} [options.filename] - Custom filename
* @param {string} [options.contentType] - Custom content type
* @returns {Request} Request instance for chaining
*/
Request.prototype.attach(field, file, options?): Request;
/**
* Add a form field to multipart request
* @param {string} name - Field name
* @param {string|number|boolean} value - Field value
* @returns {Request} Request instance for chaining
*/
Request.prototype.field(name, value): Request;Usage Examples:
const superagent = require('superagent');
const fs = require('fs');
// Upload file from filesystem
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/document.pdf');
// Upload with custom filename
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/document.pdf', 'my-document.pdf');
// Upload with options object
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/document.pdf', {
filename: 'custom-name.pdf',
contentType: 'application/pdf'
});
// Upload Buffer
const buffer = Buffer.from('Hello World');
superagent
.post('https://api.example.com/upload')
.attach('file', buffer, 'hello.txt');
// Upload Stream
const stream = fs.createReadStream('/path/to/large-file.zip');
superagent
.post('https://api.example.com/upload')
.attach('file', stream, 'archive.zip');Add non-file form fields to multipart requests.
// Mixed form with file and fields
superagent
.post('https://api.example.com/upload')
.field('title', 'My Document')
.field('description', 'A sample document')
.field('category', 'documents')
.attach('file', '/path/to/document.pdf');
// Multiple values for same field
superagent
.post('https://api.example.com/upload')
.field('tags', 'document')
.field('tags', 'pdf')
.field('tags', 'important')
.attach('file', '/path/to/document.pdf');Upload multiple files in a single request.
// Multiple files with different field names
superagent
.post('https://api.example.com/upload')
.attach('document', '/path/to/document.pdf')
.attach('image', '/path/to/image.jpg')
.attach('archive', '/path/to/data.zip');
// Multiple files with same field name
superagent
.post('https://api.example.com/upload')
.attach('files', '/path/to/file1.txt')
.attach('files', '/path/to/file2.txt')
.attach('files', '/path/to/file3.txt');
// Mixed upload with metadata
superagent
.post('https://api.example.com/upload')
.field('user_id', '12345')
.field('upload_type', 'batch')
.attach('files', '/path/to/file1.txt', 'first-file.txt')
.attach('files', '/path/to/file2.txt', 'second-file.txt');Upload files with dynamic content or from various sources.
// Upload from URL (download and upload)
const response = await superagent.get('https://example.com/remote-file.pdf');
superagent
.post('https://api.example.com/upload')
.attach('file', response.body, 'downloaded-file.pdf');
// Upload generated content
const csvData = 'name,age\nJohn,30\nJane,25';
const csvBuffer = Buffer.from(csvData);
superagent
.post('https://api.example.com/upload')
.attach('csv', csvBuffer, {
filename: 'data.csv',
contentType: 'text/csv'
});
// Upload with progress tracking
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/large-file.zip')
.on('progress', (event) => {
console.log(`Upload progress: ${event.percent}%`);
console.log(`Loaded: ${event.loaded} / Total: ${event.total}`);
});Handle common file upload errors.
// Upload with comprehensive error handling
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/document.pdf')
.field('title', 'My Document')
.end((err, res) => {
if (err) {
if (err.code === 'ENOENT') {
console.error('File not found');
} else if (err.status === 413) {
console.error('File too large');
} else if (err.status === 415) {
console.error('Unsupported file type');
} else {
console.error('Upload failed:', err.message);
}
return;
}
console.log('Upload successful:', res.body);
});
// Promise-based error handling
try {
const response = await superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/document.pdf');
console.log('Upload successful:', response.body);
} catch (err) {
console.error('Upload failed:', err.message);
}For large files, consider chunked upload patterns:
const fs = require('fs');
const path = require('path');
async function uploadLargeFile(filePath, chunkSize = 1024 * 1024) {
const stats = fs.statSync(filePath);
const totalSize = stats.size;
let uploaded = 0;
// Initialize upload session
const session = await superagent
.post('https://api.example.com/upload/init')
.send({
filename: path.basename(filePath),
size: totalSize
});
const sessionId = session.body.sessionId;
// Upload chunks
while (uploaded < totalSize) {
const start = uploaded;
const end = Math.min(uploaded + chunkSize, totalSize);
const chunk = fs.createReadStream(filePath, { start, end: end - 1 });
await superagent
.post(`https://api.example.com/upload/chunk/${sessionId}`)
.attach('chunk', chunk)
.field('offset', start.toString())
.field('size', (end - start).toString());
uploaded = end;
console.log(`Uploaded: ${uploaded}/${totalSize} bytes`);
}
// Finalize upload
const result = await superagent
.post(`https://api.example.com/upload/finalize/${sessionId}`);
return result.body;
}Validate files before uploading:
const fs = require('fs');
const path = require('path');
function validateFile(filePath) {
const stats = fs.statSync(filePath);
const ext = path.extname(filePath).toLowerCase();
// Check file size (max 10MB)
if (stats.size > 10 * 1024 * 1024) {
throw new Error('File too large (max 10MB)');
}
// Check file type
const allowedTypes = ['.pdf', '.jpg', '.jpeg', '.png', '.doc', '.docx'];
if (!allowedTypes.includes(ext)) {
throw new Error('Unsupported file type');
}
return true;
}
// Usage
try {
validateFile('/path/to/document.pdf');
const response = await superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/document.pdf');
console.log('Upload successful');
} catch (err) {
console.error('Validation or upload failed:', err.message);
}Automatic and manual content type handling:
// Automatic content type detection (based on file extension)
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/image.jpg'); // Automatically sets image/jpeg
// Manual content type override
superagent
.post('https://api.example.com/upload')
.attach('file', '/path/to/data.bin', {
filename: 'data.json',
contentType: 'application/json'
});
// Content type for Buffers
const jsonData = JSON.stringify({ key: 'value' });
const buffer = Buffer.from(jsonData);
superagent
.post('https://api.example.com/upload')
.attach('data', buffer, {
filename: 'data.json',
contentType: 'application/json'
});Install with Tessl CLI
npx tessl i tessl/npm-superagent