Silenus
Silenus

Reputation: 1

How to handle erros from multer custom storage?

I'm using multer with sharp and a custom storage, image upload is set and it works fine but I can not handle the errors correctly. It is crashing my server when I upload for example a wrong file type or when a file is too big.

on my app.js

const upload = multer({
  storage: new customStorage({
    destination: function(req, file, cb) {
      cb(
        null,
        path.join(
          __dirname,
          '/images',
          new Date().toISOString().replace(/:/g, '-') +
            '-' +
            file.originalname.replace(/\s+/g, '-')
        )
      );
    }
  }),
  limits: { fileSize: 5000000 }
});

on my customStorage.js

const fs = require('fs');
const sharp = require('sharp');
const nodePath = require('path');

function getDestination(req, file, cb) {
  cb(null, 'images');
}

function customStorage(opts) {
  this.getDestination = opts.destination || getDestination;
}

customStorage.prototype._handleFile = function _handleFile(req, file, cb) {
  this.getDestination(req, file, function(err, path) {
    if (err) return cb(err);//***the problem is here.***

    const outStream = fs.createWriteStream(path);
    const transform = sharp().resize(200, 200);

    file.stream.pipe(transform).pipe(outStream);
    outStream.on('error', cb);
    outStream.on('finish', function() {
      cb(null, {
        path: 'images/' + nodePath.basename(path),
        size: outStream.bytesWritten
      });
    });
  });
};

customStorage.prototype._removeFile = function _removeFile(req, file, cb) {
  fs.unlink(file.path, cb);
};

module.exports = function(opts) {
  return new customStorage(opts);
};

When i upload another file it says:

Error: Input buffer contains unsupported image format
Emitted 'error' event at:
    at sharp.pipeline (/Users/David/nodejs-app/node_modules/sharp/lib/output.js:687:18)

I would like to handle the errors with express like this instead.

return res.status(422).render('admin/edit-product', {flash message here.} 

That's the way I do it with other errors like when the field is empty.

Upvotes: 0

Views: 1057

Answers (1)

Max
Max

Reputation: 21

You can throw the error in your Multer custom storage (which is already being done with cb(err) ), and then catch it in a middleware for express.

const upload = multer({
  storage: new customStorage({
    destination: function(req, file, cb) {
      cb(
        null,
        path.join(
          __dirname,
          '/images',
          new Date().toISOString().replace(/:/g, '-') +
            '-' +
            file.originalname.replace(/\s+/g, '-')
        )
      );
    }
  }),
  limits: { fileSize: 5000000 }
});

var uploadMiddleware = function(req, res, next){
    var handler = upload.single('media'); //use whatever makes sense here
    handler(req, res, function(err){
        //send error response if Multer threw an error
        if(err){
            res.status(500).render('admin/edit-product', "flash message here.");
        }
        //move to the next middleware, or to the route after no error was found
        next();
    });
}

Then use the uploadMiddleware in your express route:

app.post('/route/edit', uploadMiddleware, function (req, res) {
   //handle request and render normally
});

Upvotes: 1

Related Questions