Search code examples
node.jsexpressforevermulter

Nodejs server sometimes fails to upload files using multer, express, forever


I am trying to build a simple file server to receive files from post request with multipart/form-data and I followed the multer tutorial but it seems something is not quite right and it sometimes returns 500 internal server error. The code is in the following.

var express = require('express');
var multer  = require('multer');
var mkdirp = require('mkdirp');
var app = express();
var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    var dir = 'file/' + req.body.jobid + '/';
    mkdirp(dir, function(err) {
        if(err) {
            console.error(err);
        }
    });
    cb(null, dir);
    console.log("Upload: saved to " + dir + file.originalname);
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname);
  }
});

var upload = multer({ storage: storage });

app.post('/', upload.single("file"),function (req, res, next) {
  res.status(200).end();
  next(req,res);
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

The error happens like every two requests out of ten.

The code I used to start forever

forever start app.js;

I am new to nodejs and this kind of errors (errors that happen occasionally) is killing me.

I added some functions to log the possible errors.

app.use(function(err, req, res, next) {
  console.error(err.stack);
  next(err);
});

app.use(function(err, req, res, next) {
  if (req.xhr) {
    res.status(500).send({ error: err.stack });
  } else {
    next(err);
  }
});

and it logged something like this:

Upload: saved to file/9974de5b-a9c7-4de2-92d0-5dcf277b3946/file123
Error: ENOENT, open 'file/9974de5b-a9c7-4de2-92d0-5dcf277b3946/file123'
    at Error (native)
Error: ENOENT, open 'file/9974de5b-a9c7-4de2-92d0-5dcf277b3946/file123'
    at Error (native)

Solution

  • What is likely happening, is that sometimes your code is throwing a synchronous error, which express by default will turn into a 500 response. It's pretty difficult to diagnose without knowing what the error is. What you should do is add an error handler before var server, which will catch errors and log them to console. Then when the error occurs, you'll easily be able to see it and fix the issue.

    app.use(function(err, req, res, next) {
        console.log(err);
        next(err);
    });
    
    var server = app.listen(3000, function () {
      var host = server.address().address;
      var port = server.address().port;
    
      console.log('Example app listening at http://%s:%s', host, port);
    });
    

    EDIT

    Move the line cb(null, dir); up a line, as such:

    destination: function (req, file, cb) {
        var dir = 'file/' + req.body.jobid + '/';
        mkdirp(dir, function(err) {
            if(err) {
                console.error(err);
            }
            // move cb to here
            cb(null, dir);
        });
    
        console.log("Upload: saved to " + dir + file.originalname);
      },
      filename: function (req, file, cb) {
        cb(null, file.originalname);
      }