skip to Main Content

I am sending form data from my react application over to a localhost express server. I’ve made sure that the formData I am about to sent is populated on the client side, but for some reason the req.body is always empty object on the server side. I tried using header to transfer some data to check if req was being sent, and yes I can access data from header of req on server side. It’s just the body which is empty.
Below is the client side code to send request

const handleRegister = async (
  setDisabled: React.Dispatch<React.SetStateAction<boolean>>,
  values: InitialValues,
  pictureFile: File,
  resetForm: (
    nextState?: Partial<FormikState<InitialValues>> | undefined
  ) => void,
  uri: string
) => {
  const formData = new FormData();

  Object.keys(values).map((key) => {
    if (key === "confirm_password") return;
    formData.append(key, values[key]);
  });

  formData.append("picture", pictureFile);
  formData.append("picturePath", pictureFile.name);
  const rawData = await fetch(`${uri}/auth/register`, {
    method: "POST",
    headers: {
      "Cache-Control": "no-cache",
      email: values.email,
    },
    body: formData,
  });

  const jsonData = await rawData.json();
  // Always empty
  console.log(jsonData);
};

I am using formik and again, the formData is populated properly I’ve made sure of that.

And below is my server side code.

import express from "express";
import multer from "multer";
import cors from "cors";
import bodyParser from "body-parser";
import dotenv from "dotenv";
import morgan from "morgan";
import helmet from "helmet";
import mongoose from "mongoose";
import checkRouter from "./routes/checkRouter";
import authRouter from "./routes/authRouter";
import { register } from "./controllers/auth";
import checkExistingUser from "./middlewares/checkExistingUser";
import getRandomMiliseconds from "./utils/getRandomMiliseconds";

const app = express();
app.use(cors());
app.use(morgan("common"));
app.use(helmet());
app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));
app.use(bodyParser.json({ limit: "30mb" }));
app.use(bodyParser.urlencoded({ limit: "30mb", extended: true }));
dotenv.config();

app.use("/assets", express.static("public"));

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "public/");
  },
  filename: (req, file, cb) => {
    const randomizedNumber = getRandomMiliseconds();
    cb(null, req.body.email + "-" + file.originalname + "-" + randomizedNumber);
  },
});

const uploadMiddleWare = multer({ storage: storage });

app.use("/check", checkRouter);
app.use("/auth", authRouter);

// app.post(
//   "/auth/register",
//   checkExistingUser,
//   // uploadMiddleWare.single("picture"),
//   register
// );

// In here the req.body is always empty.
app.post("/auth/register", (req, res) => {
  console.log(req.body);
  res.status(200).json(req.body);
});

mongoose.connect("mongodb://127.0.0.1:27017/SweeterDB").then(() => {
  app.listen(3001, async () => {
    console.log("Server started, listening at port 3001");
  });
});

2

Answers


  1. Move the uploadMiddleWare before the routes that need to access the request body:

    // ...
    app.use(uploadMiddleWare.single("picture"));
    app.use("/check", checkRouter);
    app.use("/auth", authRouter);
    // ...
    

    Or You can Update the register route to use the uploadMiddleWare.single middleware for the picture field:

    app.post("/auth/register", uploadMiddleWare.single("picture"), checkExistingUser, register);
    

    By placing the uploadMiddleWare before the /auth/register route, you allow multer to handle the FormData and populate the req.body with the non-file fields. The checkExistingUser and register middleware should now be able to access the data from the req.body.

    Login or Signup to reply.
  2. It seems like the issue lies in the way you are handling the multipart/form-data in your Express server. When you use bodyParser.json() middleware, it only parses JSON data in the request body, not form data. To handle multipart/form-data, you should use the multer middleware to parse the form data and make it available in req.body.

    Install the multer package if you haven’t already:

    npm install multer
    

    Here how you can modify your server-side code to use multer properly:

    import express from "express";
    import multer from "multer";
    import cors from "cors";
    import dotenv from "dotenv";
    import morgan from "morgan";
    import helmet from "helmet";
    import mongoose from "mongoose";
    import checkRouter from "./routes/checkRouter";
    import authRouter from "./routes/authRouter";
    import { register } from "./controllers/auth";
    import checkExistingUser from "./middlewares/checkExistingUser";
    import getRandomMiliseconds from "./utils/getRandomMiliseconds";
    
    const app = express();
    app.use(cors());
    app.use(morgan("common"));
    app.use(helmet());
    app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));
    dotenv.config();
    
    app.use("/assets", express.static("public"));
    
    const storage = multer.diskStorage({
      destination: (req, file, cb) => {
        cb(null, "public/");
      },
      filename: (req, file, cb) => {
        const randomizedNumber = getRandomMiliseconds();
        cb(null, req.body.email + "-" + file.originalname + "-" + randomizedNumber);
      },
    });
    
    const uploadMiddleWare = multer({ storage: storage });
    
    app.use("/check", checkRouter);
    app.use("/auth", authRouter);
    
    app.post(
      "/auth/register",
      checkExistingUser,
      uploadMiddleWare.single("picture"), // Use multer middleware to handle form data
      register
    );
    
    mongoose.connect("mongodb://127.0.0.1:27017/SweeterDB").then(() => {
      app.listen(3001, async () => {
        console.log("Server started, listening at port 3001");
      });
    });
    

    With this modification, multer will properly handle the multipart/form-data, and you will be able to access req.body as expected in the register function and other route handlers.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search