9

I have a simple form with two file input fields. One is about an image, and the other is about a mp3 file.

I have an express server which utilizes multer as file upload system. I'd like to save the image inside the img, and the mp3 file inside the music folder.

This is what I tried so far:

var musicUpload = multer({dest: 'music'});
var imgUpload = multer({dest: 'img'});

app.post('music', 
         musicUpload.single('music'), 
         imgUpload.single('img'), 
         function (req, res) {
             ...
         });

While this is the form:

<form action="post" enctype="multipart/form-data" action="music">
    <input type="file" id="img" name="img">
    <input type="file" id="music" name="music">
    <input type="submit" value="Send">
</form>

I need to handle the 2 different files in a different way, this is the reason why I used "single" twice. But, unluckly, I receive a "Unexpected field" error message.

How can achieve the result?

Ps. There are many question on SO about multiple files uploading, but none of them solved my specific problem. Don't be too much fast at flagging this question :)

3 Answers3

8

You could try using something like DiskStorage. As per their docs: https://github.com/expressjs/multer

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    if (file.mimetype === 'audio/mp3') {
      cb(null, 'songs')
    } else if (file.mimetype === 'image/jpeg') {
      cb(null, 'img')
    } else {
      console.log(file.mimetype)
      cb({ error: 'Mime type not supported' })
    }
  }
})


var upload = multer({ storage: storage })

and then on the endpoints themselves do:

var upload = multer({storage}); 
  router.post('/song', upload.any(), function(req, res) { 
  ...  
});

this is probably cleaner then your approach and i think gives the functionality you're looking for as it gives you more granular control over saving those files. (with edits by @cristian)

Matt Pengelly
  • 1,480
  • 2
  • 20
  • 34
2

you can add if else statement in multer storage destination and use file.fieldname to determine your input field name and store it in different folder.

var storage = multer.diskStorage({
    destination: function (req, file, cd) {
        if (file.fieldname === 'img') {
            cd(null, '/img');
        }

        else if (file.fieldname === 'music') {
            cd(null, '/music');
        }
        
    },

    filename: function (req, file, cd) {
      cd(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
    }
});

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

and in your post method this will be the solid partner. reference

var cpUpload = upload.fields([{ name: 'img', maxCount: 1 }, { name: 'music', maxCount: 1 }]);
app.post('/music', cpUpload, function (req, res, next) { 

    console.log(req.file, req.body);
    res.redirect('/');

});
frustrated-dev
  • 431
  • 6
  • 29
1

Consider looking at the solutions shown here in this similar question, it shows how to use the upload.fields[...] provided by multer for multi-file uploads that gives you more control withe the chance to define if the field is .single or .array using the maxCount:.

OR

Look into my repo (a nuxt-express-mongodb app) under server where i use multer to upload a song/music and image from 1 post request using upload.fields[...] to see a full working implementation.

Emmanuel Neni
  • 325
  • 4
  • 11