Reputation: 755
I have searched but i couldn't find exact solution..When i uploading image it should allow only jpg,jpeg,gif,png..If any other file it should show message in UI. I have used the following code
var upload = multer({ storage: storage,
fileFilter: function (req, file, cb) {
var ext = path.extname(file.originalname);
if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
return cb(new Error('Wrong extension type'));
// if(Error){
// console.log("error file type")
// }
}
cb(null, true)
}
});
If i try to upload pic rather than jpeg,jpg,png,git It showing error ..But how to display as message in my application page itself
Error: Wrong extension type
at fileFilter (D:\Vishnu\octopus new\app\routes.js:912:24)
at wrappedFileFilter (D:\Vishnu\octopus new\node_modules\multer\index.js:44:7)
at Busboy.<anonymous> (D:\Vishnu\octopus new\node_modules\multer\lib\make-middleware.js:114:7)
at emitMany (events.js:127:13)
at Busboy.emit (events.js:201:7)
at Busboy.emit (D:\Vishnu\octopus new\node_modules\busboy\lib\main.js:38:33)
at PartStream.<anonymous> (D:\Vishnu\octopus new\node_modules\busboy\lib\types\multipart.js:213:13)
at emitOne (events.js:96:13)
at PartStream.emit (events.js:188:7)
at HeaderParser.<anonymous> (D:\Vishnu\octopus new\node_modules\dicer\lib\Dicer.js:51:16)
at emitOne (events.js:96:13)
at HeaderParser.emit (events.js:188:7)
at HeaderParser._finish (D:\Vishnu\octopus new\node_modules\dicer\lib\HeaderParser.js:68:8)
at SBMH.<anonymous> (D:\Vishnu\octopus new\node_modules\dicer\lib\HeaderParser.js:40:12)
at emitMany (events.js:127:13)
at SBMH.emit (events.js:201:7)
Kindly help me in this issue.. Thanks in Advance
Upvotes: 3
Views: 9932
Reputation: 198
const fileTypes = /jpeg|JPEG|jpg|JPG|png|PNG|gif|GIF/;
const mimetype = fileTypes.test(file.mimetype);
if (mimetype) {
return cb(null, true);
}else{
req.fileValidationError = "Your Error Message";
return cb(null, false, req.fileValidationError);
// if the above code is not working, try this:
return cb(req.fileValidationError, false);
}
Upvotes: 0
Reputation: 667
Alternate way to handle exceptions with the help of middleware
router.post("/v1/user/create",uploadFile,customBadRequestException,customBadFileRequestException)
Custom exceptions
exports.customBadRequestException = (req,res,next) => {
if(!req.body || !req.body.data || !req.body.data.length || !req.file || !req.file.filename){
return res.status(400).send({ message: "Bad request" });
}
next();
};
exports.customBadFileRequestException = (req,res,next) => {
if (! /\.(jpe?g|png|gif|bmp)$/i.test(req.file.filename)) {
return res.status(400).send({ message: "Please upload only images" });
}
next();
};
Multer Config
const multer = require("multer");
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null,"/Users/path/Desktop/testFiles");
},
filename: (req, file, cb) => {
cb(null, `${Date.now()}-${file.originalname}`);
},
});
var uploadFile = multer({ storage: storage}).single("file");
module.exports = uploadFile;
Upvotes: 0
Reputation: 36104
fileFilter callback should be:
var upload = multer({
storage: storage,
fileFilter: function (req, file, cb) {
var ext = path.extname(file.originalname);
if(ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
cb(new Error('Wrong extension type'), false);
}
cb(null, true)
}
});
Error handling in request:
MulterError
const multer = require("multer");
router.post('/upload', function(req, res) {
upload.single('field name')(req, res, function(err) {
// FILE SIZE ERROR
if (err instanceof multer.MulterError) {
return res.end("Max file size 2MB allowed!");
}
// INVALID FILE TYPE, message will return from fileFilter callback
else if (err) {
return res.end(err.message);
}
// FILE NOT SELECTED
else if (!req.file) {
return res.end("File is required!");
}
// SUCCESS
else {
console.log("File uploaded successfully!");
console.log("File response", req.file);
}
)}
})
Upvotes: 2
Reputation: 33
Adding to this answer, which works like a charm by the way.
If you want a catch-all for errors that result from a file not accepted by MIME type or because a file was not attached, you can do the following:
Set your FileFilter function to something like this:
const upload = multer({
storage: //storage declaration here,
fileFilter: (req, file, cb) => {
if (
!file.mimetype.includes("image/png") &&
!file.mimetype.includes("image/jpeg")
) {
return cb(null, false);
}
cb(null, true);
}
});
and then in your route or wherever your req
, res is scoped, you can catch the error and respond accordingly by checking the req.file
variable that normally holds the uploaded file information:
if (!req.file) {
console.log("No file received or invalid file type");
return res.status(400).send({
message: "No file received or invalid file type",
success: false
});
}
Without setting a new req
variable to hold a ValidationError
, you can respond gracefully to the user if they don't provide a valid file.
This works because the FileFilter will successfully filter out a file that doesn't match your validation even without throwing an error in the callback, but instead of throwing an error, it just won't proceed with accepting the file. I don't understand fully why the callback in multer is built that way as the method of throwing errors does not bubble up to your route or controller.
With the above code, however, if the fileFilter does its job, when you check that req.file
exists (or doesn't in this case) with if(!req.file){}
, you can catch both no-file submissions and failed validation at once without the messy error that gets thrown from fileFilter's callback :)
Upvotes: 2
Reputation: 228
I've been struggling with this problem for a while now as well. I thought I had found one solution but it ended up not working that well for me but after enough tinkering and looking around tonight I found an answer that works for me. I hope this helps. I actually found this question while looking around for an answer.
So what I did was created req.fileValidationError in your example as so:
var upload = multer({
fileFilter: function (req, file, cb) {
let ext = path.extname(file.originalname);
if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
req.fileValidationError = "Forbidden extension";
return cb(null, false, req.fileValidationError);
}
cb(null, true);
}
});
Then in your route you want to check req.fileValidationError with an if statement. If it exists then you know there is a forbidden extension.
Assuming you are using express under the app variable, and you are wanting single images to be sent, it would look something like so:
app.post('/your-upload-route', upload.single("your-input-name-here"), function(req, res) {
if (req.fileValidationError) {
// return res.sendFile();
// or return res.end();
// or even res.render(); whatever response you want here.
}
});
I hope this helps! If anyone else has a different way of doing this I'd be happy to update my answer as well as seeing other people's insight.
Upvotes: 19