Uploading multiple files with multer, but from different fields?

Viewed 69527

How can I have multer accept files from multiple file type fields?

I have the following code that uploads a single file, using multer in node.js:

var storage =   multer.diskStorage({
  destination: function (req, file, callback) {
    callback(null, './public/uploads');
  },
  filename: function (req, file, callback) {
    callback(null, file.fieldname + '-' + Date.now());
  }
});

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

app.post('/rest/upload', upload.array('video', 1), function(req, res, next){
    ...
}

From the following form, on the condition only the video field has a value (if I specify both I get an 'Unexpected field' error):

<form action="/rest/upload" method="post" enctype="multipart/form-data">
   <label>Video file: </label> <input type="file" name="video"/> 
   <label>Subtitles file: </label> <input type="file" name="subtitles"/> 
   <input type="submit"/>
</form>

It is not clear from the documentation how to approach this? Any suggestions would be appreciated. BTW I have tried the following parameter variations, without success:

app.post('/rest/upload', [upload.array('video', 1), upload.array('subtitles', 1)] ...
app.post('/rest/upload', upload.array('video', 1), upload.array('subtitles', 1), ...
app.post('/rest/upload', upload.array(['video', 'subtitles'], 1),  ...
6 Answers

Using Multer Upload Files From Two Fields of Separate Forms on Different Pages In this example I have two fields - resume and image. Resume in one form and Image in other. Both are on separate pages. First import dependencies

const path = require('path'); // for getting file extension
const multer = require('multer'); // for uploading files
const uuidv4 = require('uuidv4'); // for naming files with random characters

Define fileStorage and fileFilter:

const fileStorage = multer.diskStorage({
  destination: (req, file, cb) => { // setting destination of uploading files        
    if (file.fieldname === "resume") { // if uploading resume
      cb(null, 'resumes');
    } else { // else uploading image
      cb(null, 'images');
    }
  },
  filename: (req, file, cb) => { // naming file
    cb(null, file.fieldname+"-"+uuidv4()+path.extname(file.originalname));
  }
});

const fileFilter = (req, file, cb) => {
  if (file.fieldname === "resume") { // if uploading resume
    if (
      file.mimetype === 'application/pdf' ||
      file.mimetype === 'application/msword' ||
      file.mimetype === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
    ) { // check file type to be pdf, doc, or docx
      cb(null, true);
    } else {
      cb(null, false); // else fails
    }
  } else { // else uploading image
    if (
      file.mimetype === 'image/png' ||
      file.mimetype === 'image/jpg' ||
      file.mimetype === 'image/jpeg'
    ) { // check file type to be png, jpeg, or jpg
      cb(null, true);
    } else {
      cb(null, false); // else fails
    }
  }
};

Middleware for multer

app.use(
  multer(
    { 
      storage: fileStorage, 
      limits:
        { 
          fileSize:'2mb' 
        }, 
      fileFilter: fileFilter 
    }
  ).fields(
    [
      { 
        name: 'resume', 
        maxCount: 1 
      }, 
      { 
        name: 'image', 
        maxCount: 1 
      }
    ]
  )
);

And then call your routes. You may need to add csrf protection or authentication along with this for security. But this should work fine.

If you want to upload multiple files/images from the same form, I have used the below code and it works fine. The path of the image is stored in the database; I will skip the database path and go straight to the upload function and how the fields are passed to the save function.

    const path = require('path');
    const multer = require('multer');
    const storage = multer.diskStorage({
        destination: (req, file, cb) => {
           if (file.fieldname === "profile") {
               cb(null, './uploads/profiles/')
           }
           else if (file.fieldname === "natid") {
               cb(null, './uploads/ids/');
           }
           else if (file.fieldname === "certificate") {
               cb(null, './uploads/certificates/')
           }
        },
        filename:(req,file,cb)=>{
            if (file.fieldname === "profile") {
                cb(null, file.fieldname+Date.now()+path.extname(file.originalname));
            }
          else if (file.fieldname === "natid") {
            cb(null, file.fieldname+Date.now()+path.extname(file.originalname));
          }
          else if (file.fieldname === "certificate") {
            cb(null, file.fieldname+Date.now()+path.extname(file.originalname));
          }
        }
    });
    const upload = multer({
        storage: storage,
        limits: {
            fileSize: 1024 * 1024 * 10
        },
        fileFilter: (req, file, cb) => {
            checkFileType(file, cb);
        }
    }).fields(
        [
            {
                name:'profile',
                maxCount:1
            },
            {
                name: 'natid', maxCount:1
            },
            {
                name: 'certificate', maxCount:1
            }
        ]
    );
    
    function checkFileType(file, cb) {
        if (file.fieldname === "certificate") {
            if (
                file.mimetype === 'application/pdf' ||
                file.mimetype === 'application/msword' ||
                file.mimetype === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
              ) { // check file type to be pdf, doc, or docx
                  cb(null, true);
              } else {
                  cb(null, false); // else fails
              }
        }
        else if (file.fieldname === "natid" || file.fieldname === "profile") {
            if (
                file.mimetype === 'image/png' ||
                file.mimetype === 'image/jpg' ||
                file.mimetype === 'image/jpeg'||
                fiel.mimetype==='image/gif'
              ) { // check file type to be png, jpeg, or jpg
                cb(null, true);
              } else {
                cb(null, false); // else fails
              }
            }
        }
    //at the save function 

 upload(req, res, (err) => {
        if (err) {
            console.log(err);
        } else {
            if (req.file == "undefined") {
                console.log("No image selected!")
            } else {
                let datecreated = new Date();
                let fullnames = req.body.firstname + ' ' + req.body.lastname;
                let formatedphone = '';
                let phone = req.body.personalphone;
                if (phone.charAt(0) == '0') {
                    formatedphone = '+254' + phone.substring(1);
                } else if ((phone.charAt(0) == '+') && (phone.length > 12 || phone.length <= 15)) {
                    formatedphone = phone
                }
                let teachers = {
                    "teacherid": teacherid,
                    "schoolcode": req.body.schoolcode,
                    "fullnames": fullnames,
                    "email": req.body.email,
                    "dateofbirth": req.body.dateofbirth,
                    "nationalid": req.body.nationalid,
                    "personalphone": formatedphone,
                    "profile": req.files.profile[0].path,
                    "natid": req.files.natid[0].path,
                    "certificate":req.files.certificate[0].path
                }
                connection.query('INSERT INTO teachers SET ?', teachers, (error, results, fields) => {`enter code here`
                    if (error) {
                        res.json({
                            status: false,
                            message: 'there are some error with query'
                        })
                        console.log(error);
                    } else {console.log("Saved successfully");
}

this worked for Me. complete example

var multer = require('multer')
var storage = multer.diskStorage({


destination: function(req, file, callback) {
    callback(null, './public/audio');
  },
  filename: function(req, file, callback) {
    console.log(file);
    if(file.originalname.length>6)
      callback(null, file.fieldname + '-' + Date.now() + file.originalname.substr(file.originalname.length-6,file.originalname.length));
    else
      callback(null, file.fieldname + '-' + Date.now() + file.originalname);

  }
});

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


router.post('/save/audio',upload.fields([{
  name: 'audio', maxCount: 1
}, {
  name: 'graphic', maxCount: 1
}]) ,(req, res) => {
  
  const audioFile = req.files.audio[0];
  const audioGraphic = req.files.graphic[0];
  const fileName = req.body.title;


  saveAudio(fileName,audioFile.filename,audioGraphic.filename,req.body.artist,function (error,success) {
    req.flash('success','File Uploaded Successfully')

    res.redirect('/')
  });

})
upload(req, res, (err) => {
        if (err) {
            console.log(err);
        } else {
            if (req.file == "undefined") {
                console.log("No image selected!")
            } else {
                let datecreated = new Date();
                let fullnames = req.body.firstname + ' ' + req.body.lastname;
                let formatedphone = '';
                let phone = req.body.personalphone;
                if (phone.charAt(0) == '0') {
                    formatedphone = '+254' + phone.substring(1);
                } else if ((phone.charAt(0) == '+') && (phone.length > 12 || phone.length <= 15)) {
                    formatedphone = phone
                }
                let teachers = {
                    "teacherid": teacherid,
                    "schoolcode": req.body.schoolcode,
                    "fullnames": fullnames,
                    "email": req.body.email,
                    "dateofbirth": req.body.dateofbirth,
                    "nationalid": req.body.nationalid,
                    "personalphone": formatedphone,
                    "profile": req.files.profile[0].path,
                    "natid": req.files.natid[0].path,
                    "certificate":req.files.certificate[0].path
                }
                connection.query('INSERT INTO teachers SET ?', teachers, (error, results, fields) => {
                    if (error) {
                        res.json({
                            status: false,
                            message: 'there are some error with query'
                        })
                        console.log(error);
                    } else {

console.log('Saved successfully');}

Related