Express File Upload is a simple Express.js middleware that provides file upload functionality by wrapping around the Busboy library. It automatically parses multipart forms and makes uploaded files available through the req.files object with a clean, intuitive API.
npm install express-fileuploadconst fileUpload = require('express-fileupload');ESM:
import fileUpload from 'express-fileupload';const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();
// Default options
app.use(fileUpload());
app.post('/upload', (req, res) => {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
// The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
let sampleFile = req.files.sampleFile;
// Use the mv method to move the file to your desired upload directory
sampleFile.mv('/path/to/upload/directory/filename.jpg', (err) => {
if (err) return res.status(500).send(err);
res.send('File uploaded!');
});
});Express File Upload is built around several key components:
Creates Express middleware for handling file uploads with extensive configuration options.
/**
* Creates Express middleware for handling file uploads
* @param {Object} options - Configuration options for file upload behavior
* @returns {Function} Express middleware function (req, res, next) => void
*/
function fileUpload(options);Usage Examples:
// Basic usage with default options
app.use(fileUpload());
// With custom options
app.use(fileUpload({
limits: { fileSize: 50 * 1024 * 1024 }, // 50MB limit
useTempFiles: true,
tempFileDir: '/tmp/',
debug: true
}));
// With advanced configuration
app.use(fileUpload({
createParentPath: true,
safeFileNames: true,
preserveExtension: 4,
abortOnLimit: true,
responseOnLimit: 'File size limit has been reached',
uploadTimeout: 120000, // 2 minutes
hashAlgorithm: 'sha256'
}));Comprehensive configuration options for controlling upload behavior.
interface FileUploadOptions {
/** Enable debug logging */
debug?: boolean;
/** Custom logger with .log() method */
logger?: Object;
/** Upload timeout in milliseconds */
uploadTimeout?: number;
/** Custom file handler function */
fileHandler?: boolean | Function;
/** Decode URI-encoded filenames */
uriDecodeFileNames?: boolean;
/** Sanitize unsafe characters in filenames */
safeFileNames?: boolean | RegExp;
/** Preserve file extensions during sanitization */
preserveExtension?: boolean | number;
/** Abort upload when size limit reached */
abortOnLimit?: boolean;
/** Response message for size limit violations */
responseOnLimit?: string;
/** Custom limit handler function */
limitHandler?: Function;
/** Create parent directories if they don't exist */
createParentPath?: boolean;
/** Parse nested form fields */
parseNested?: boolean;
/** Use temporary files instead of memory */
useTempFiles?: boolean;
/** Directory for temporary files */
tempFileDir?: string;
/** File permissions for temporary files */
tempFilePermissions?: number;
/** Hash algorithm for file checksums */
hashAlgorithm?: string;
}Default Values:
debug: falselogger: consoleuploadTimeout: 60000 (60 seconds)fileHandler: falseuriDecodeFileNames: falsesafeFileNames: falsepreserveExtension: falseabortOnLimit: falseresponseOnLimit: 'File size limit has been reached'limitHandler: falsecreateParentPath: falseparseNested: falseuseTempFiles: falsetempFileDir: 'tmp' (relative to current working directory)tempFilePermissions: 0o644hashAlgorithm: 'md5'Each uploaded file becomes an object with properties and methods for file manipulation.
interface UploadedFile {
/** Original filename */
name: string;
/** File content as Buffer (empty if useTempFiles is true) */
data: Buffer;
/** File size in bytes */
size: number;
/** File encoding */
encoding: string;
/** Path to temporary file (if useTempFiles is true) */
tempFilePath: string;
/** Whether file was truncated due to size limits */
truncated: boolean;
/** MIME type of the file */
mimetype: string;
/** File checksum using configured hash algorithm */
md5: string;
/**
* Move file to specified location
* @param {string} filePath - Destination file path
* @param {Function} callback - Optional callback function
* @returns {Promise|undefined} Promise if no callback provided
*/
mv(filePath: string, callback?: Function): Promise<void> | undefined;
}Usage Examples:
app.post('/upload', (req, res) => {
const uploadedFile = req.files.myFile;
// Access file properties
console.log('Filename:', uploadedFile.name);
console.log('Size:', uploadedFile.size);
console.log('MIME type:', uploadedFile.mimetype);
console.log('MD5 checksum:', uploadedFile.md5);
// Move file using callback
uploadedFile.mv('/uploads/' + uploadedFile.name, (err) => {
if (err) return res.status(500).send(err);
res.send('File uploaded successfully');
});
});
// Using Promise-based approach
app.post('/upload-async', async (req, res) => {
try {
const uploadedFile = req.files.myFile;
await uploadedFile.mv('/uploads/' + uploadedFile.name);
res.send('File uploaded successfully');
} catch (err) {
res.status(500).send(err);
}
});The middleware automatically adds file objects to the Express request object.
interface Request {
/**
* Object containing uploaded files, where keys are form field names
* and values are UploadedFile objects or arrays of UploadedFile objects
*/
files: { [fieldName: string]: UploadedFile | UploadedFile[] } | null;
}Usage Examples:
app.post('/single-upload', (req, res) => {
// Single file upload
const file = req.files.singleFile;
// file is an UploadedFile object
});
app.post('/multi-upload', (req, res) => {
// Multiple files with same field name
const files = req.files.multipleFiles;
if (Array.isArray(files)) {
// files is an array of UploadedFile objects
files.forEach(file => {
console.log(file.name);
});
} else {
// Single file (files is an UploadedFile object)
console.log(files.name);
}
});
app.post('/mixed-upload', (req, res) => {
// Mixed upload with different field names
const profilePic = req.files.profilePicture;
const documents = req.files.documents; // Could be single file or array
const avatar = req.files.avatar;
});All Busboy configuration options can be passed through the options object for advanced multipart parsing control.
interface BusboyOptions {
/** Field name size limit */
fieldNameSize?: number;
/** Field value size limit */
fieldSize?: number;
/** Number of non-file fields limit */
fields?: number;
/** File size limit per file */
fileSize?: number;
/** Number of files limit */
files?: number;
/** Number of parts limit */
parts?: number;
/** Header pairs limit */
headerPairs?: number;
}Usage Examples:
// Combine express-fileupload options with Busboy options
app.use(fileUpload({
// Express-fileupload options
useTempFiles: true,
tempFileDir: '/tmp/',
createParentPath: true,
// Busboy options
limits: {
fileSize: 10 * 1024 * 1024, // 10MB per file
files: 5, // Maximum 5 files
fieldSize: 1024, // 1KB per field
fields: 10 // Maximum 10 non-file fields
}
}));The middleware integrates with Express error handling and can generate errors for various conditions:
// Error handling example
app.use(fileUpload({
uploadTimeout: 60000,
abortOnLimit: true,
limits: { fileSize: 1024 * 1024 } // 1MB
}));
app.use((err, req, res, next) => {
console.error('File upload error:', err);
res.status(500).send('Upload failed');
});// Memory-based (default) - good for small files
app.use(fileUpload()); // Files stored in req.files[].data Buffer
// Temporary files - better for large files
app.use(fileUpload({
useTempFiles: true,
tempFileDir: '/tmp/'
})); // Files stored on disk, accessible via req.files[].tempFilePathapp.post('/upload', (req, res) => {
if (!req.files || !req.files.document) {
return res.status(400).send('No file uploaded');
}
const file = req.files.document;
// Validate file type
if (!file.mimetype.startsWith('image/')) {
return res.status(400).send('Only images allowed');
}
// Validate file size (additional check)
if (file.size > 5 * 1024 * 1024) {
return res.status(400).send('File too large');
}
// Process file
const filename = Date.now() + '_' + file.name;
file.mv('./uploads/' + filename, (err) => {
if (err) return res.status(500).send(err);
res.json({ message: 'Success', filename: filename });
});
});app.use(fileUpload({
safeFileNames: true, // Remove dangerous characters
preserveExtension: 4, // Keep up to 4-char extensions
uriDecodeFileNames: true // Decode URI-encoded names
}));