Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handling not working #336

Closed
edi opened this issue Apr 4, 2016 · 6 comments
Closed

Error handling not working #336

edi opened this issue Apr 4, 2016 · 6 comments

Comments

@edi
Copy link

edi commented Apr 4, 2016

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.

@edi
Copy link
Author

edi commented Apr 4, 2016

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.

@wesbos
Copy link

wesbos commented Aug 15, 2016

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

@edi
Copy link
Author

edi commented Aug 25, 2016

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 ).

@LinusU
Copy link
Member

LinusU commented Aug 27, 2016

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 :)

@JerryLafumeDev
Copy link

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 :)

im still getting undefined :/

@evazquezb
Copy link

im still getting undefined :/

2024 and im having same problem.

if you mean you get undefined instead of the json, this can help you

Maybe multer have a bug in a callback function when error is passed.
So, i decide not to send error in the cb and work fine for example:

In your case
In the fileFilter function if mimetype isnt 'image/jpg' send the json in the response and execute the callback without an error like this:

res.json({error:"invalid format"});
cb(null,false);

this way the file isnt save it and the server send the json with error

if the mimetype is correct execute cb(null,true);

finally in the avatarUpoad function NOT validate an error, just send a json without error like this
res.json({error:false});

const multer = require('multer');
router.post('/avatar', (req, res) => {
const storage = multer.diskStorage({
        destination :"your directory",
        filename : function(req,file,cb){
            cb(null,file.fieldname + Date.now().toString() + "_" + file.originalname);
        }
    });
 const fileFilter =  (req, file, cb) => {
    if (file.mimetype !== 'image/jpeg') {
      res.json({error:"invalid format"});
      cb(null,false)
    }
     cb(null, true)
  }  

const limits = { fileSize: "the limit" };

multer({ storage ,limits , fileFilter }).single('avatar')(req, res ,error => res.json({error:false}) )

} );

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants