Skip to content

ExpressJS - Handling File Uploads

Express.js - Handling File Uploads with Multer

Section titled “Express.js - Handling File Uploads with Multer”

File uploads are a common feature in web applications, from profile pictures to document submissions. In Express.js, the standard library for handling multipart/form-data, which is primarily used for uploading files, is Multer.

Multer is a middleware that adds a file object (for single uploads) or a files object (for multiple uploads) to the request object. These objects contain information about the uploaded file(s).

First, install Multer using npm.

npm install multer

The simplest way to use Multer is to specify a destination directory. Multer will then save uploaded files with randomly generated names to that directory.

import express from 'express';
import multer from 'multer';
import path from 'path';
const app = express();
// Configure Multer to store files in an 'uploads/' directory
const upload = multer({ dest: 'uploads/' });
// Create the route to handle single file uploads
// The 'avatar' string must match the 'name' attribute of the file input field in your HTML form.
app.post('/profile', upload.single('avatar'), (req, res, next) => {
// req.file contains information about the uploaded file
console.log('File details:', req.file);
// req.body will contain the text fields, if there were any
console.log('Body details:', req.body);
res.status(200).send('File uploaded successfully!');
});
app.listen(3000, () => console.log('Server started on port 3000'));

The req.file object will look like this:

{
fieldname: 'avatar',
originalname: 'profile-picture.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'uploads/',
filename: 'a1b2c3d4e5f6a1b2c3d4e5f6',
path: 'uploads/a1b2c3d4e5f6a1b2c3d4e5f6',
size: 12345
}

For more control over where files are stored and how they are named, use multer.diskStorage.

const storage = multer.diskStorage({
destination: (req, file, cb) => {
// The destination directory for uploads
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
// Create a unique filename to avoid overwrites
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
});
const uploadWithCustomStorage = multer({ storage: storage });
app.post('/photo', uploadWithCustomStorage.single('image'), (req, res) => {
res.send(`File uploaded and saved as ${req.file.filename}`);
});

It’s crucial to validate uploads to ensure users only submit allowed file types and sizes. You can configure this in Multer’s options.

const uploadValidated = multer({
storage: storage, // Using the custom storage from before
limits: {
fileSize: 1024 * 1024 * 5 // 5MB file size limit
},
fileFilter: (req, file, cb) => {
// Allow only images (jpeg, jpg, png)
const allowedTypes = /jpeg|jpg|png/;
const mimetype = allowedTypes.test(file.mimetype);
const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
if (mimetype && extname) {
return cb(null, true);
}
cb(new Error('Error: File upload only supports the following filetypes - ' + allowedTypes));
}
});
// Route using the validated upload middleware
app.post('/upload-image', uploadValidated.single('productImage'), (req, res) => {
res.json({ message: 'Image uploaded successfully!', file: req.file });
}, (error, req, res, next) => {
// Custom error handler for Multer errors
res.status(400).json({ error: error.message });
});

To upload multiple files in a single request, use upload.array(fieldname, maxCount).

// This will accept up to 10 files with the field name 'gallery'
app.post('/gallery', uploadValidated.array('gallery', 10), (req, res) => {
// req.files will be an array of file objects
console.log(req.files);
res.send(`${req.files.length} files uploaded successfully!`);
});

To test your upload endpoint, you can use an API client like Postman. Create a POST request, select the Body tab, choose form-data, and for the key, switch the type from ‘Text’ to ‘File’ to select your file. The key name must match the fieldname you specified in your Multer configuration (e.g., ‘avatar’, ‘image’, ‘gallery’).