I use Multer for uploading file or images. Problem is that it is impossible to validate the real file extension.
Example: If someone rename filename.exe
to filename.png
, then it is still validate to upload.
Can you suggest me the solution to handle this issue? Thanks
I used like this but need verify real ext of files
fileFilter: async function (req, file, callback) {
var ext = path.extname(file.originalname);
if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg' && ext !== '.zip') {
return callback(new Error('Only images and zip are allowed'));
}
// I want next function to validate real ext of files here.
callback(null, true);
},
Starting with Multer 2.x.x You can check for both the extension and the MIME type of the uploaded parameter. Here is a sample code.
const storage = multer.diskStorage({
destination: './uploadedContent',
filename: function(_req, file, cb){
cb(null,file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
var upload = multer({
storage: storage,
limits: {
fields: 5,
fieldNameSize: 50, // TODO: Check if this size is enough
fieldSize: 20000, //TODO: Check if this size is enough
// TODO: Change this line after compression
fileSize: 15000000, // 150 KB for a 1080x1080 JPG 90
},
fileFilter: function(_req, file, cb){
checkFileType(file, cb);
}
}).single('postPicture');
function checkFileType(file, cb){
// Allowed ext
const filetypes = /jpeg|jpg|png|gif/;
// Check ext
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
// Check mime
const mimetype = filetypes.test(file.mimetype);
if(mimetype && extname){
return cb(null,true);
} else {
cb('Error: Images Only!');
}
}
Don't forget to check your file permissions too. You don't want the uploaded file to be executed somehow. Sadly the latest npm release is 1.4.3 where the Multer mime type is based on the type property that comes from the client. That property at least in windows is dependent of the file extension, not on the file content.
There are two steps:
fileFilter
optionsDefine whitelist mime type:
const whitelist = [
'image/png',
'image/jpeg',
'image/jpg',
'image/webp'
]
Example of the first step:
const upload = multer({
storage: multer.diskStorage({
destination: 'public/uploads/',
filename: (req, file, cb) => {
const name = slugify(file.originalname, { lower: true })
cb(null, `${new Date().getTime()}-${name}`)
},
}),
fileFilter: (req, file, cb) => {
if (!whitelist.includes(file.mimetype)) {
return cb(new Error('file is not allowed'))
}
cb(null, true)
}
})
Example of the second step:
const FileType = require('file-type')
// ....
// first step
// ....
/**
* Second step
*/
app.use('store', upload.single('image'), async (req, res, next) => {
const meta = await FileType.fromFile(req.file.path)
if (!whitelist.includes(meta.mime)) {
return next(new Error('file is not allowed'))
}
res.json({
file: req.file,
body: req.body,
})
})
I tried to rename a document.pdf
-> document.png
and it passed the first check but got caught on the second one.
Basically what you need is something which can verify the extension with original file type.
Copied from a blog
var upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
}
});
Blog Link
If this doesn't work for you, consider using a separate module which verify file type from buffer data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With