Multer places uploaded files into request fields after its middleware runs. The original example used disk storage under /tmp and built a filename from the field name, time, random suffix, and original extension.
Storage
// Multer upload config
const fs = require('fs');
const path = require('path');
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname))
}
})
const upload = multer({storage: storage});
Keeping an extension does not verify the uploaded file’s actual type or contents.
A single file
app.post('/uploadPhoto', (req, res, next) => {
upload.single('filename_here')(req, res, function (err) {
if (err) {
// A Multer error occurred when uploading.
res.json({msg: err.message})
} else {
// Everything went fine.
// req.file
// {
// fieldname: 'filename_here',
// originalname: 'example-upload.png',
// encoding: '7bit',
// mimetype: 'image/png',
// destination: '/tmp/',
// filename: 'filename_here-1607694392023-220481630',
// path: '/tmp/filename_here-1607694392023-220481630',
// size: 5907
// }
const file = req.file;
console.log(file);
// Delete tmp
try {
// fs.unlinkSync(file.path);
} catch (e) {
// Ignore
console.error(e);
}
res.json({msg: 'ok'});
}
});
})
Test
curl --location --request POST '<host>:<port>/uploadPhoto' \
--form 'filename_here=@"/example/upload.png"'
This listing includes the original curl test after the route code; it is labeled text rather than a standalone JavaScript module. The example workstation path is generalized.
Named fields
const fields = [{ name: 'front', maxCount: 1 }, { name: 'back', maxCount: 1 }]
app.post('/uploadPhoto', (req, res, next) => {
upload.fields(fields)(req, res, function (err) {
if (err) {
// A Multer error occurred when uploading.
res.json({msg: err.message})
} else {
// Everything went fine.
// file
// {
// fieldname: 'xxx',
// originalname: 'Screen Shot 2020-12-11 at 20.28.29.png',
// encoding: '7bit',
// mimetype: 'image/png',
// destination: '/tmp/',
// filename: 'xxx-1607694392023-220481630',
// path: '/tmp/xxx-1607694392023-220481630',
// size: 5907
// }
// array of `photos` files
const frontF = req.files['front'][0];
const backF = req.files['back'][0];
console.log('frontF', frontF);
console.log('backF', backF);
// Delete tmp
try {
// fs.unlinkSync(file.path);
} catch (e) {
// Ignore
console.error(e);
}
res.json({msg: 'ok'});
}
});
});
Test
curl --location --request POST '<host>:<port>/users/uploadPhotos' \
--header 'Authorization: Bearer <token>' \
--form 'front=@"/path/to/front.png"' \
--form 'back=@"/path/to/back.png"'
The handlers assume expected files exist before indexing them. Authentication, file-count/size limits, content validation, error status codes, and reliable cleanup are not established by these small examples. Their deletion calls are commented out, so the demo does not actually guarantee temporary-file removal.
No endpoint, upload, or file deletion was executed for this revision.