Search code examples
node.jsexpressmodulemulter

Modularizing Multer Functionality Issue


I am trying to clean up my controllers by modularizing my multer module functions, which allow me to upload multiple files with my forms. The current code presented below works, but I want put the multer function in a new file. I assumed that simply taking the function and exporting it from another file would work, but for some reason I'm hitting a time out during my form POST, despite calling the console.log at the start of the multer code. It appears that something within that code is stopping the process, but no error message is thrown. Does anyone see what might be causing the error?

Multer called within route file:

var aws = require('aws-sdk');
var multer = require('multer');
var multerS3 = require('multer-s3');
var moment = require('moment');

var uploadDate = new moment().format("YYYY-MM-DD");
var s3 = new aws.S3();
var options = {
    Bucket: process.env.AWS_BUCKET,
    Expires: 60
};

if(app.get('env') === 'production' || app.get('env') === 'staging'){
    options.ACL = 'private'
} else {
    options.ACL = 'public-read'
};

//////////Multer code being called

var upload = multer({
    storage: multerS3({
        s3: s3,
        bucket: options.Bucket,
        contentType: multerS3.AUTO_CONTENT_TYPE,
        acl: options.ACL,
        key: function(req, file, cb){
            var fileNameFormatted = file.originalname.replace(/\s+/g, '-').toLowerCase();
            cb(null, req.session.organizationId + '/' + uploadDate + '/' + fileNameFormatted);
        }
    }),
    fileFilter: function(req, file, cb){
        if(!file.originalname.match(/\.(jpg|jpeg|png|gif|csv|xls|xlsb|xlsm|xlsx)$/)){
            return cb('One of your selected files is not supported', false);
        }
        cb(null, true);
    }
}).array('fileUpload', 5);

///////Post route calling multer and rest of form submission

.post(function(req, res){

     upload(req, res, function(){
        if(err){
            console.log('Multer upload error');
            req.flash('error', err);
            res.redirect(req.get('referer'));
            return;
        }

        ... MORE CODE ...
    })
});

/controllers/multer.js, which contains the multer code:

var express = require('express');
var app = express();
var aws = require('aws-sdk');
var multer = require('multer');
var multerS3 = require('multer-s3');
var moment = require('moment');

var s3 = new aws.S3();
var uploadDate = new moment().format("YYYY-MM-DD");

var options = {
    Bucket: process.env.AWS_BUCKET,
    Expires: 60,
    //ContentType: req.query.file_type
};

if(app.get('env') === 'production' || app.get('env') === 'staging'){
    options.ACL = 'private'
} else {
    options.ACL = 'public-read'
};

module.exports = {

    //Annotation file upload
    annotationFileUpload: function(){
        multer({
            storage: multerS3({
                s3: s3,
                bucket: options.Bucket,
                contentType: multerS3.AUTO_CONTENT_TYPE,
                acl: options.ACL,
                key: function(req, file, cb){
                    console.log("key called");
                    var fileNameFormatted = file.originalname.replace(/\s+/g, '-').toLowerCase();
                    cb(null, req.session.organizationId + '/' + uploadDate + '/' + fileNameFormatted);
                }
            }),
            fileFilter: function(req, file, cb){
                console.log("file filter called");
                if(!file.originalname.match(/\.(jpg|jpeg|png|gif|csv|xls|xlsb|xlsm|xlsx)$/)){
                    return cb('One of your selected files is not supported', false);
                }
                cb(null, true);
            }
        }).array('fileUpload', 5);
    }
}

Importing /controller/multer and calling route:

var multerFile = require('./components/multer');

    .post(function(req, res){

    multerFile.annotationFileUpload(req, res, function(err){
                if(err){
                    console.log('Multer upload error');
                    req.flash('error', err);
                    res.redirect(req.get('referer'));
                    return;
                }
           ....MORE CODE....
         })
    });

Solution

  • You need to get rid of the wrapper function, since multer() returns the middleware function itself. The reason it times out is because you're calling a function that just creates the middleware and immediately discards it and then does nothing else (like responding to the request).

    So change this:

    annotationFileUpload: function(){
        multer({
           // ...
        }).array('fileUpload', 5);
    }
    

    to this:

    annotationFileUpload: multer({
      // ...
    }).array('fileUpload', 5)