Search code examples
javascriptnode.jsexpressxmlhttprequestmulter

Node.js: set Multer destination based on FormData values


I'm creating an XMLHttpRequest (xhr) that sends a FormData object that contains a file and some values to the Node.js(Express) server. I'm using Multer, as I can't use bodyParser with multipart data.

router.post("/submit", function(req, res) {
    var storage = multer.diskStorage({
        // set destination here
    })

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

    upload(req, res, function (err) {
        // I can access req.body here
    });
});

The destination that I set in storage will depend on the values of the body object (like req.body.product). But I'm not able to access req.body before calling multer(). How can I access req.body before setting multer.storage?


Solution

  • You need to use the destination config property for diskStorage() as shown in the multer documentation. For example:

    var storage = multer.diskStorage({
      destination: function(req, file, cb) {
        var newAbsoluteDir = /* calculate based on `req.body` here */;
        cb(null, newAbsoluteDir);
      }
    });
    
    var upload = multer({ storage });
    
    // ...
    
    router.post('/submit', upload.any(), function(req, res) {
      // ...
    });
    

    As the documentation notes, any non-file fields you need to access inside those multer callbacks need to be positioned before the file field you're processing because multipart/form-data requests have their fields ordered. So if you have a static HTML form, it's the literal position of the input, select, etc. elements that matters. For XHR, it's the order in which you call formData.append() for each field.