16
votes

I'm playing around with file uploading in Node.js/Multer.

I got the the storage and limits working. But now im playing around with filefilter to simply deny some files by mimetype like this:

fileFilter: function (req, file, cb) {
 if (file.mimetype !== 'image/png') {
  return cb(null, false, new Error('goes wrong on the mimetype'));
 }
 cb(null, true);
}

When a file gets uploaded that is not a PNG it wont accept it. But it also won't trigger the if(err)

When the file is to big it does generate the error. So somehow I need to generate an err on filefilter as well but im not sure how and guess new Error is wrong.

So, how am I supposed to generate an error if the file is not correct? What am I doing wrong?

Full code:

var maxSize = 1 * 1000 * 1000;

var storage =   multer.diskStorage({
  destination: function (req, file, callback) {
    callback(null, 'public/upload');
  },
  filename: function (req, file, callback) {
    callback(null, file.originalname);
  }
});


var upload = multer({
   storage : storage,
   limits: { fileSize: maxSize },
   fileFilter: function (req, file, cb) {
     if (file.mimetype !== 'image/png') {
       return cb(null, false, new Error('I don\'t have a clue!'));
     }
     cb(null, true);
   }

 }).single('bestand');


router.post('/upload',function(req,res){
    upload(req,res,function(err) {
        if(err) {
              return res.end("some error");
        }
    )}
)}
4
I am looking for this multer({storage, filteFilter...}) thank you.Aljohn Yamaro

4 Answers

23
votes

fileFilter function has access to request object (req). This object is also available in your router.

Therefore in fileFitler you can add property with validation error or validation error list (you can upload many files, and some of them could pass). And in router you check if property with errors exists.

in filter:

fileFilter: function (req, file, cb) {
 if (file.mimetype !== 'image/png') {
  req.fileValidationError = 'goes wrong on the mimetype';
  return cb(null, false, new Error('goes wrong on the mimetype'));
 }
 cb(null, true);
}

in router:

router.post('/upload',function(req,res){
    upload(req,res,function(err) {
        if(req.fileValidationError) {
              return res.end(req.fileValidationError);
        }
    )}
)}
6
votes

You can pass the error as the first parameter.

multer({
  fileFilter: function (req, file, cb) {
    if (path.extname(file.originalname) !== '.pdf') {
      return cb(new Error('Only pdfs are allowed'))
    }

    cb(null, true)
  }
})
4
votes

Change the fileFilter and pass an error to the cb function:

function fileFilter(req, file, cb){
   if(file.mimetype !== 'image/png'){
       return cb(new Error('Something went wrong'), false);
    }
    cb(null, true);
};
1
votes

fileFilter callback should be:

fileFilter: async (req, file, cb) => {
    if (file.mimetype != 'image/png') {
        cb(new Error('goes wrong on the mimetype!'), false);
    }
    cb(null, true);
}

Error handling in request:

  • access multer error using MulterError
const multer = require("multer");

router.post('/upload', function(req, res) {
    upload(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);
        }

    )}
})