Multer accepts an options object, the most basic of which is the dest
property, which tells Multer where to upload the files. In case you omit the options object, the files will be kept in memory and never written to disk.
By default, Multer will rename the files so as to avoid naming conflicts. The renaming function can be customized according to your needs.
The following are the options that can be passed to Multer.
Key | Description |
dest or storage | Where to store the files |
fileFilter | Function to control which files are accepted |
limits | Limits of the uploaded data |
preservePath | Keep the full path of files instead of just the base name |
In an average web app, only dest
might be required, and configured as shown in the following example.
const upload = multer({ dest: 'uploads/' })
If you want more control over your uploads, you'll want to use the storage
option instead of dest
. Multer ships with storage engines DiskStorage
and MemoryStorage
const storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(
null,
file.fieldname + '-' + Date.now() + path.extname(file.originalname)
);
},
});
const fileFilter = (req, file, cb) => {
//Image only
if (file.mimetype.split('/')[0] === 'image') cb(null, true);
else cb(null, false);
};
const upload = multer({
storage,
fileFilter,
limits: { fileSize: 10000000 }, // 10MB
});
const express = require('express');
const multer = require('multer');
const app = express();
const path = require('path');
app.get('/', (req, res) => {
res.send(`
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="myFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
const storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
callback(
null,
file.fieldname + '-' + Date.now() + path.extname(file.originalname)
);
},
});
const fileFilter = (req, file, cb) => {
if (file.mimetype.split('/')[0] === 'image') cb(null, true);
else cb(new multer.MulterError('File is not of the correct type'), false);
};
const upload = multer({
storage,
fileFilter,
limits: { fileSize: 10000000 }, // 10MB
});
app.post('/api/upload', upload.any(), function (req, res, next) {
// Upload to cloudinary or aws s3
return res.json({ success: true, data: req.files });
});
const errHandler = (error, req, res, next) => {
const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
return res.status(statusCode).json({
success: false,
message: error.code,
});
};
app.use(errHandler);
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000');
});