Axios post request not setting Content-Type to multipart/form-data

Viewed 3430

Im trying to upload an image to cloudinary from react, i am unable to make a post request using axios . This is the code :

 const onSubmit = async (data) => {
    const { files } = document.querySelector('input[type="file"]');
    console.log(data);
    if (data.files !== undefined || data.files !== null || data.files !== "") {
      setLoading(true);
      const formData = new FormData();
      formData.append("file", files[0]);
      formData.append("upload_preset", cloudinary_preset);
      const options = {
        headers: { "Content-Type": "multipart/form-data" },
        data: formData,
      };
      const res = await axios.post(
        `https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
        options
      );
      const img = await res.json();
      const imgUrl = img.secure_url;
      data.thumbnail = imgUrl;
      console.log(data.thumbnail);
      console.log(res);
      setLoading(false);
    } else {
      data.thumbnail = "";
    }
   };

the response that i got on my browser console : enter image description here

But when i use fetch , i am successfully uploaded my images . Here is the code :

 const onSubmit = async (data) => {
    const { files } = document.querySelector('input[type="file"]');
    console.log(data);
    if (data.files !== undefined || data.files !== null || data.files !== "") {
      setLoading(true);
      const formData = new FormData();
      formData.append("file", files[0]);
      formData.append("upload_preset", cloudinary_preset);
      const options = {
        method: "POST",
        body: formData,
      };
      const res = await fetch(
        `https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
        options
      );
      const img = await res.json();
      const imgUrl = img.secure_url;
      data.thumbnail = imgUrl;
      console.log(data.thumbnail);
      console.log(res);
      setLoading(false);
    } else {
      data.thumbnail = "";
    }
    };

the responses :

enter image description here

My guess that i conclude from the web console is on the headers part, when i use axios even tho i already change the headers to content-type:multipart/form-data , it still being sent as application/json. But then again im still learning to read the console log , if someone know what is really happening please share your opinion!

2 Answers

You are getting application/json type because you are passing JS object options to data part in your Axios post call.

Setting headers should be done in 3rd argument of .post method:

Here is modified code where options variable is removed:

const onSubmit = async (data) => {
  const { files } = document.querySelector('input[type="file"]');
  console.log(data);
  if (data.files !== undefined || data.files !== null || data.files !== '') {
    setLoading(true);

    const formData = new FormData();
    formData.append('file', files[0]);
    formData.append('upload_preset', cloudinary_preset);
    const res = await axios.post(
      `https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`, 
      formData, 
      {
        headers: { 'Content-Type': 'multipart/form-data' }
      }
    );
    const img = await res.json();
    const imgUrl = img.secure_url;
    data.thumbnail = imgUrl;
    console.log(data.thumbnail);
    console.log(res);
    setLoading(false);
  } else {
    data.thumbnail = '';
  }
};

Axios docs https://axios-http.com/docs/api_intro:

axios.post(url[, data[, config]])

NOTE

I think that when you add FormData type of data to body, axios will se Content-Type to be multiplart/form-data implicitly.

Turns out that axios return a promise , hence i need to use then&catch to make it works, here is my working solution :

const onSubmit = async (data, e) => {
    const { files } = document.querySelector('input[type="file"]');
    console.log(data);
    if (data.files !== undefined || data.files !== null || data.files !== "") {
      setLoading(true);
      const formData = new FormData();
      formData.append("file", files[0]);
      formData.append("upload_preset", cloudinary_preset);
      await axios
        .post(
          `https://api.cloudinary.com/v1_1/${cloudinary_id}/image/upload`,
          formData
        )
        .then((result) => {
          const img = result.data;
          const imgUrl = img.secure_url;
          data.thumbnail = imgUrl;
          setLoading(false);
        })
        .catch((err) => console.log(err));
    } else {
      data.thumbnail = "";
    }

    try {
      setLoading(true);
      await authAxios
        .post("/api/project/", data)
        .then((res) => {
          console.log(res.data);
        })
        .catch((e) => {
          console.log(e);
        });
      setLoading(false);
      reset();
    } catch (err) {
      console.log(err);
    }
  };

After the images is uploaded to cloudinary , i fetch it to the data which then is gonna be sent to my mongodb along with the text form data.

Related