skip to Main Content

I want Multer allows just photo to be uploaded but it doesn’t work and gives request.file = undefined and at the same time the file.mimetype = image/jpeg which is correct

Here is a clip from Postman:
enter image description here

I checked the headers also and it contains Content-Type = multipart/form-data; boundary=<calculated when request is sent>

then I tried and removed fileFilter: multerFilter configurations from Multer and the surprise that everything worked fine without any single problem. Here is the related code:

const multerStorage = multer.memoryStorage();

// 2) Creating a multer filter (to test if the uploaded file is really an image):
const multerFilter = (request, file, cb) => {
  if (file.mimetype.startsWith("image")) cb(null, true);
  cb(new AppError(400, `The only accepted files are images, please select an image ${request.file} file tyep: ${file.mimetype}`), false);
};

const upload = multer({ storage: multerStorage, fileFilter: multerFilter });

exports.updateMyPhoto = upload.single("photo");

Please help me find what’s wrong with my fileFilter configuration

UPDATE:

I switched between the two conditions inside multerFilter and the program is working perfectly now. the new code:

const multerFilter = (request, file, cb) => {
  if (!file.mimetype.startsWith("image")) cb(new AppError(400, `The only accepted files are images, please select an image ${request.file} file tyep: ${file.mimetype}`), false);
  cb(null, true);
  };

I still don’t know the reason for this behaviour so I’d appreciate your help

2

Answers


  1. You should call your callback function cb with return keyword. Otherwise after the first callback function call, your code will continute and eventually the second callback function will be called and this will cause this confusing problem to be occur. To solve this update your code using return keyword:

    const multerFilter = (request, file, cb) => {
      if (file.mimetype.startsWith("image")) return cb(null, true);
      return cb(new AppError(400, `The only accepted files are images, please select an image ${request.file} file tyep: ${file.mimetype}`), false);
    };
    

    To understand how your current implementation behaves, run the following code snippet and see the outputs.

    const filterCheckWithoutReturnKeyword = (number, callback) => {
      if(number > 10) callback('Number is greater than 10!');
      callback('Number is less than 10!');
    };
    
    const filterCheckWithReturnKeyword = (number, callback) => {
      if(number > 10) return callback('Number is greater than 10!');
      return callback('Number is less than 10!');
    };
    
    const callbackFn = (message) => console.log(message);
    
    filterCheckWithoutReturnKeyword(5, callbackFn);
    filterCheckWithoutReturnKeyword(15, callbackFn);
    
    // Seperator log
    console.log('---------------');
    
    filterCheckWithReturnKeyword(5, callbackFn);
    filterCheckWithReturnKeyword(15, callbackFn);
    Login or Signup to reply.
  2. Your first set of code does work… it just doesn’t work the way you expect. You think you are coding an if/else but it looks like you are just calling the callback (cb) twice. That means the second callback will always execute.

    There is a lot of debate about whether or not to include curly braces in your code and there are arguments for both, but if you want to avoid one source of bugs then always include curly braces. This answer explains it best.

    Try to change your first code to this:

    const multerFilter = (request, file, cb) => {
       if (file.mimetype.startsWith("image")){
          cb(null, true);
       } else{
          cb(new AppError(400, `The only accepted files are images, please 
       select an image ${request.file} file tyep: ${file.mimetype}`), false);
       }
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search