Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multer: upload different file types in different folders

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 :)

like image 788
Cristian Traìna Avatar asked Jun 01 '18 10:06

Cristian Traìna


2 Answers

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)

like image 63
Matt Pengelly Avatar answered Oct 20 '22 21:10

Matt Pengelly


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('/');

});
like image 26
frustrated-dev Avatar answered Oct 20 '22 20:10

frustrated-dev