Multer: Error handling not working

Created on 4 Apr 2016  路  4Comments  路  Source: expressjs/multer

Hello ! I want to be able to handle the limits and the fileFilter errors and I'm doing just as the doc says:

var upload = multer().single('avatar')

app.post('/profile', function (req, res) {
  upload(req, res, function (err) {
    if (err) {
      // An error occurred when uploading
      return
    }

    // Everything went fine
  })
})

My code looks like this

var upload = multer({ 
    dest: UPLOADS_DIR,
    limits: { fileSize: MAX_PIC_FILESIZE },
    fileFilter: ( req, file, cb ) => {
            cb( null, file.mimetype == 'image/jpeg' )
    },
});

// POST - uploading user profile picture
router.post( '/avatar', ( req, res ) => { 

    console.log( 'uploading' );
    upload.single( 'avatar', ( err ) => {

        if ( err )
        {
            console.log( err )
            return res.send({ error: 'file_too_large' })
        }

        console.log( 'uploaded file for', res.locals.userId, req.file.filename );

        var filename = res.locals.userId + '_' + App.getCurrentTimestamp() + '.jpg';
        fs.rename( req.file.path, UPLOADS_DIR + '/' + res.locals.userId, ( err ) => {

            if ( err )
            {
                console.log( err )
                return res.send({ error: 'file_too_large' })    
            }

            console.log( 'renamed file', UPLOADS_DIR + '/' + req.file.filename, filename )
            res.send({ url: PUBLIC_DIR + '/' + filename });

        });

    });

});

Bare in mind that it works perfectly if I remove the inner upload.single() and I add it as middleware:

router.post( '/avatar', upload.single('avatar'), ( req, res ) => { ... }

But then, the downside is I can't get the error anymore.
Any solution for this ? The uploading log gets triggered correctly, but it doesn't fire the upload if not set as middleware.

Most helpful comment

Sorry for not commenting on this earlier. The last example is really good, the reason the fileFilter thing isn't showing up as an error is because it isn't intended to. If you want to trigger an error, you can supply it to the callback, so something like this:

var multer = require('multer')({
  dest: App.uploadsDir,
  limits: { fileSize: App.maxMediaFileSize },
  fileFilter: (req, file, cb) => {
    if (file.mimetype !== 'image/jpeg') {
      return cb(new Error('Only jpeg images allowed'))
    }

    cb(null, true)
  }
})
var avatarUpload = multer.single('avatar')

router.post('/avatar', (req, res) => {
  avatarUpload(req, res, (err) => {
    if (err) return res.send({ error: 'invalid_file' })

    console.log('save the file', req.file)
  })
})

also, you shouldn't call the avatarUpload twice! Either add it as a middleware _or_ call it manually.

I hope this clears everything up, feel free to reopen if you have more problems :)

All 4 comments

Ok, I have managed to figure out I can change the code to something like:

var upload = multer.single('avatar');

router.post('/avatars', upload , ( req, res ) => {
   upload( req, res, ( err ) => {
       if ( err ) return console.log( err );
   });
});

Now it gets triggered, everything works fine, but when trying to upload an invalid file ( pdf ) which is filtered in fileFilter the err variable is not filled up with any data, it just passes through.

Additionally I have added if ( err || !req.file ) to trigger sending a JSON error message to the client. But I feel like that err should not behave like this.

Did you ever get this fixed? Having a heck of a time trying get get error handling on fileFilter working

Hi @wesbos I came up with the following code, which works just fine for me.

var multer  = multer({ 
             dest: App.uploadsDir, 
             limits: { fileSize: App.maxMediaFileSize }, 
             fileFilter: ( req, file, cb ) => { 
                      console.log( file.mimetype ); 
                      cb( null, file.mimetype == 'image/jpeg'  ) 
             }
        }),
    avatarUpload = multer.single('avatar');

router.post( '/avatar', avatarUpload, ( req, res ) => { 

    avatarUpload( req, res, ( err ) => {

        if ( err || !req.file )
             return res.send({ error: 'invalid_file' })

        console.log( 'save the file', req.file );

    });

});

Still, the err variable is empty when the fileFilter triggers ( at least it triggers ), so I'm checking if req,file is undefined in this case, which implies the file did not get through the filter, thus, returning an invalid_file error.

Hope it helps ( using node sharp to process the images ).

Sorry for not commenting on this earlier. The last example is really good, the reason the fileFilter thing isn't showing up as an error is because it isn't intended to. If you want to trigger an error, you can supply it to the callback, so something like this:

var multer = require('multer')({
  dest: App.uploadsDir,
  limits: { fileSize: App.maxMediaFileSize },
  fileFilter: (req, file, cb) => {
    if (file.mimetype !== 'image/jpeg') {
      return cb(new Error('Only jpeg images allowed'))
    }

    cb(null, true)
  }
})
var avatarUpload = multer.single('avatar')

router.post('/avatar', (req, res) => {
  avatarUpload(req, res, (err) => {
    if (err) return res.send({ error: 'invalid_file' })

    console.log('save the file', req.file)
  })
})

also, you shouldn't call the avatarUpload twice! Either add it as a middleware _or_ call it manually.

I hope this clears everything up, feel free to reopen if you have more problems :)

Was this page helpful?
0 / 5 - 0 ratings