multer req.files undefined with axios in react

Viewed 606

I want to post a formData using axios to node js route and then save image files into images folder. I'm using multer to read multipart/form-data from axios. I'm receiving productInfo object from req.body which is correct. here is my code:

const addNewProduct = () => {

        const newProduct = {
            name: name,
            cost: cost,
            size: size,
            color: color,
            material: material,
            discount: discount,
            description: description,
            category: category
        };

        const nulls  = Object.values(newProduct).filter(p => p === null);

        if(nulls.length === 0 && images.imageFiles) {
            let productFormData = new FormData();
            productFormData.append('productInfo', JSON.stringify(newProduct));
            productFormData.append('productImages', [...images.imageFiles]);
    
            const addUrl = "http://localhost:8080/cpnl/addproduct";
            axios({
                method: "POST",
                url: addUrl,
                data: productFormData,
                headers: { "Content-Type": "multipart/form-data" }
            })
                .then((response) => {
                    console.log(response.data.msg);
                })
                .catch((response) => {
                    console.error(response);
                });
        }else {
            Notiflix.Notify.Warning("Check your inputs!");
            console.log(nulls);
            console.log("product: \n" + JSON.stringify(newProduct));
        }
};

then I receive the data in node js using multer like this:

multer config:

const storage = multer.diskStorage({
    destination: "./public/images",
    filename: (req, file, cb) => {
        cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
    }
});

const upload = multer({
    storage: storage,
    limits:{fileSize: 1000000},
    fileFilter: function(req, file, cb){
        checkFileType(file, cb);
    }
}).array("productImages");

function checkFileType(file, cb) {
  // Allowed ext
  const filetypes = /jpeg|jpg|png/;
  // Check ext
  const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
  // Check mime
  const mimetype = filetypes.test(file.mimetype);

  if(mimetype && extname){
    return cb(null,true);
  } else {
    cb('Error: Images Only!');
  }
}

multer route:

router.post('/addproduct', async (req, res) => {
    upload(req, res, (err) => {
        if(err) {
            res.status(400).json({
                msg: err
            });
        } else {
            if(req.files == undefined) {
                res.status(400).json({
                    msg: "Error: No file selected! please contact the developer."
                });
            } else {
                //problem occures here
                console.log( "images: " + req.body.productImages + "\n");
                data = req.body.productInfo;
                res.status(200).json({
                    msg: "Files uploaded!"
                });
                console.log("data" + data);
            }
        }
    });
});

I'm receiving image files inside req.body.productImages as Object file. all of this code looks good at first but multer isn't uploading image files!
why images are inside req.body.productImages?
why they aren't inside req.files?
what is happening here?

1 Answers

In your multer route code you need to change like following way

router.post('/addproduct', upload, async (req, res, next) => {/**
  YOUR LOGIC GOES HERE
*/}

Because upload is a multer reference and returns express middleware. So it will update req object with required values you're expecting req.files.

Note: req.body.productImages exist because req object not processed by multer

Related