'React Native + Expo + Axios file upload not working because axios is not sending the form data to the server

I am trying to upload an image with react native front end and axios to my back end.

This is how pic the image

const pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: false,
      aspect: [9, 16],
      quality: 1,
    });

    console.log(result.uri);

    if (!result.cancelled) {
      console.log(result);
      setPhoto(result);
    }
  };

now you can see clearly that I am setting up the photo state with the ImagePicker library.

Then I create a form data instance:

     let img_to_upload = {  
        type: 'image/jpeg',    
        name: 'random-file-name',  
        uri: Platform.OS === 'android' ? photo.uri : photo.uri.replace('file://', ''),
    };  

    let formData = new FormData();
    formData.append("title", 'this is tandom text');
    formData.append("file", img_to_upload);

here you can see clearly I have initiated a formdata object and then adding two fields to the form.

  1. title
  2. file

And last but not least, I send this to the server:

axios({
      method: 'POST',
      url: U_R_L,  
      data: formData,
      transformRequest: (d) => d, 
      headers: { 
        "Content-Type": "multipart/form-data; charset=utf-8; boundary=------random-boundary",
      }
    })
    .then((response) => {
       console.log("response : ");  
       console.log(response.data);    
    }, (error) => {
        console.log("error : "); 
        console.log(error); 
    })
    .then(() => {
      setProgress(false);
    });

But it never sends any file to the server.

Here is the error:

enter image description here

But when I test the same endpoint with my REST client, it works.



Solution 1:[1]

Axios' FormData is broken since v0.25 for react-native. They tried to optimize the FormData detection util for no real reason. Unfortunately, the proper detection fails for non browser environments.

You can find a workaround here for now: https://github.com/axios/axios/issues/4406#issuecomment-1048693170

TL;DR

const formData = new FormData();
...
const response = await axios.post('/URL', formData, {
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  transformRequest: (data, headers) => {
    return formData; // this is doing the trick
  },
});

Just pass a transformRequest and return your formData and everything will "work" magically again. This is a workaround though (I've spent 5 hours on this issue) and should hopefully be fixed in an upcoming version.

Solution 2:[2]

there is no no need to set the content-type header in your request. It automatically identify your request contains the buffer data. so you just pass the request without setting multipart content-type header.

I'm also confused with this same issue. my MacBook is sending the request without any issue by using postman, and my android device is having issues sending the multipart request.

Solution

Poor network connection is the major issue in this part. So just change your mobile network to any other network, which has the better internet connectivity. and check again. surely it solved your issue

Native javascript query for sending the multipart data - axios is also using this same native library

 var data = new FormData();
    data.append("file", {
                          name: 'image.png',
                          type: 'image/png,
                          uri: 'file:///file-cache-url'
                        }, "image.png");
     
    var xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    
    xhr.addEventListener("readystatechange", function() {
      if(this.readyState === 4) {
        console.log(this.responseText);
      }
    });

xhr.open("POST", "http://127.0.0.1:3000/data/upload");

xhr.send(data);

Solution 3:[3]

Fetch image as BLOB

 const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", "FILE_URI_HERE", true);
    xhr.send(null);
  });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hirbod
Solution 2
Solution 3 BYIRINGIRO Emmanuel