Search code examples
node.jsreactjspostmanmulter

Node js (multer) req.file and req.files always undefined in react js but working fine with templating engines


I'm trying to upload images to my server using Multer. If I use any templating engine, the req.file and req.files are working fine. But when I try to upload images with postman or jsx form in react, It returns undefined.

I'm using: Multer - 1.4.2 Express - 4.17.1 Node - 14.16.1

server.js

const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const path = require("path");
const app = express();
const port = 5000;
//Routes Import
const data = require("./routes/router");

//Database Connection
mongoose
  .connect("mongodb://localhost/newConnectSix", {
   useNewUrlParser: true,
   useUnifiedTopology: true,
   useCreateIndex: true,
})
.then(console.log("connected!"));

//MiddleWares
app.use(cors());
app.use(express.json());

//Route
app.use("/", data);

//Listening the port
app.listen(port, () => {
console.log(`Listening to ${port}`);
});

multer.js

const multer = require("multer");

//set storage
var storage = multer.diskStorage({
 destination: function (req, res, cb) {
 cb(null, "uploads");
 },
filename: function (req, file, cb) {
  var ext = file.originalname.substr(file.originalname.lastIndexOf("."));
  cb(null, file.fieldname + "-" + Date.now() + ext);
},
});

module.exports = store = multer({ storage: storage });

router.js

const express = require("express");
const store = require("../middleware/multer");
const router = express.Router();

router.post("/uploadmultiple", store.array("images", 12), (req, res) => {
  const files = req.files;
  console.log(req.files);
});

module.exports = router;

form.jsx

<form
  onSubmit={handleSubmit}
  action="/uploadmultiple"
  encType="multipart/form-data"
  method="POST"
>
<label htmlFor="">Upload images:</label>
  <input
   name="images"
   type="file"
   className="form-control"
   multiple
   />
/>

handleSubmit Function

const apiEndpoint = "http://localhost:5000/uploadmultiple";

const handleSubmit = async (e) => {
e.preventDefault();
await axios.post(apiEndpoint);
};

Solution

  • You're taking control of form submission with onSubmit and e.preventDefault(), but not sending the form with axios. You have two options:

    1. Either remove the onSubmit handler and let the browser do the request for you:

      render() {
        return (
          <form
            action="/uploadmultiple"
            encType="multipart/form-data"
            method="POST"
          >
          // ...
        );
      }
      
    2. Or do the request yourself by constructing a form and sending it with axios:

      const handleSubmit = async (e) => {
        e.preventDefault();
      
        const form = new FormData();
        for (const file of e.target.files) {
          form.append('images', file);
        }
      
        await axios.post(apiEndpoint, form, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        });
      };