2

I'm trying to upload files using React Hook Form and send them to my backend, where I'm using multer with Cloudinary for handling file uploads. When I test the API using Postman, req.files is populated correctly. However, when I submit the form from my React frontend, req.files is undefined. please help!

NewStampForm.jsx

export default function NewStampForm() {
  const auth = useAuthUser();
  const authHeader = useAuthHeader();

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const onSubmit = async (formData) => {
    console.log(formData);
    try {
      const res = await axios.post(
        `${import.meta.env.VITE_BACKEND_URL}/stamps`,
        formData,
        {
          headers: {
            Authorization: authHeader,
          },
        }
      );
    } catch (e) {
      console.log(e);
    }
  };

  return (
    <div>
      <div className="text-xl">New Stamp</div>
      <form onSubmit={handleSubmit(onSubmit)} encType="mu">
        <input
          {...register("title", { required: true })}
          placeholder="Stamp title"
        />
        {errors.title && <span>This field is required</span>}

        <input {...register("price", { required: true })} type="number" />
        {errors.price && <span>This field is required</span>}
        <input
          {...register("img", { required: true })}
          type="file"
          name="img"
          multiple
        />
        {errors.img && <span>This field is required</span>}

        <input type="submit" />
      </form>
    </div>
  );
}

Controller

const createNewStamp = async (req, res) => {
  try {
    const { title, price, img } = req.body;
    console.log(req.files);
    const newStamp = await Stamp.create({ title, price });
    res.status(200).json(newStamp);
  } catch (e) {
    errorResponse(res, e);
  }
};

cloudinary stuff

require("dotenv").config();
const cloudinary = require("cloudinary").v2;
const { CloudinaryStorage } = require("@fluidjs/multer-cloudinary");

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_key: process.env.CLOUDINARY_KEY,
  api_secret: process.env.CLOUDINARY_SECRET,
});

const storage = new CloudinaryStorage({
  cloudinary: cloudinary,
  params: {
    folder: "Mudrank", // Optional: Folder for uploaded files in Cloudinary
    allowed_formats: ["jpg", "jpeg", "png"], // Optional: Restrict allowed file types
  },
});

module.exports = {
  cloudinary,
  storage,
};

Stamp Route

router
  .route("/")
  .get(verifyCircle, getAllStamps)
  .post(verifyCircle, upload.array("img"), createNewStamp);

req.files is just undefined when I send it through the React hook form. However, when I use postman to send the req.body, it is defined.

Here is the request payload

img just shows {0:{}, 1:{}}

0

1 Answer 1

2

Got it working by using the FormData interface and modifying the onSubmit function on the React Form. Here is the code for anyone struggling with the same issue:

const onSubmit = async (formData) => {
const formDataObj = new FormData();
formDataObj.append("title", formData.title);
formDataObj.append("price", formData.price);

for (const file of formData.img) {
  formDataObj.append("img", file);
}

try {
  const res = await axios.post(
    `${import.meta.env.VITE_BACKEND_URL}/stamps`,
    formDataObj,
    {
      headers: {
        Authorization: authHeader,
      },
    }
  );
} catch (e) {
  console.log(e);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.