axios: Axios don't send form data in react-native

I’ve try to send a form data with axios but i can’t, in chrome dev tools no content appears in the request. Making a same request via postman the API response normally.

  (newData) => {
   const data = new FormData();
   data.append('name', 'raphael');
   data.append('file', {
       uri: newData.image.path,
       type: 'image/jpeg',
       name: 'teste'
   });
   return axios.post(`${constants.development.URL_API}/file`, data, 
       headers: {
           'Content-Type': 'multipart/form-data',
       },
   })`

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 7
  • Comments: 46 (4 by maintainers)

Most upvoted comments

Y’all, I appreciate the direction but “just test a file upload in React Native” isn’t that easy. I don’t often work in React Native and it would take a decent amount of time to spin up a project with file uploads to test with.

I do have a simple POST with form data that works in React Native:

    const formData = new FormData();
    formData.append("data", true);

    const config = {
      headers: {
        "Content-Type": "multipart/form-data; charset=utf-8;"
      }
    };

    axios.post(URL, formData, config).then(
      response => {
        console.log({ response });
      },
      error => {
        console.log({ error });
      }
    );

true gets stringified when sent to the server, which is interesting.

That said, if anyone can provide an example that I can easily spin up, I’m happy to look into it more.

This bug still happens with latest axios, why was this closed?

@emilyemorehouse File uploads work perfectly in a browser environment, they only fail on react native. As you mentioned yourself - your tests were outside of react native environment, I would start there 😃

Try a simple file upload in react native and simply check the wireshark traces, you don’t even need a working server…

i have same issues and my body when i check in debug is string

screen shot 2018-10-26 at 11 12 10 am

and here my code

        const formData = new FormData();
        formData.append('photo', {
          uri: response.uri.replace('file://', ''),
          mineType: 'image/jpeg',
          fileType: 'image/jpg',
          type: 'image/jpg',
          name: 'test.jpg'
        });

        console.log('form data', formData);

         Axios({
           method: 'post',
           url: 'https://dev-host.luxstay.net/api/rooms/10740/photos',
           data: formData,
           headers: {
             Authorization: token,
             'Content-Type': 'multipart/form-data'
           }
         });

Update : An error occurred because the app was in debug mode. When i turn off debug mode , it worked

I added a type inside the image object like "Image.type='image/png" just before append and also changed the content type to "Content-Type":"multipart/form-data" :

        image.type='image/png'
        formData.append("resource", image);
        return axios
          .post('yourBAckendUrl', formData, {
            headers: {
              Authorization: "yourTokenHere",
              "Content-Type": "multipart/form-data"
            }
          })

Hope this help someone.

Thanks for your help! I was able to upload my picture with the iOS Simunator but not with the android one.

After I did set the image type to ‘image/jpeg’ I stopped having the Network Error.

const formData = new FormData();
formData.append('file', {
  uri: pictureUri,
  type: 'image/jpeg',
  name: 'profile-picture'
})

For anyone that this may be of help, if you don’t know the type of the content that will be sent over, use the multipart/form-data. It sounds obvious reading this now, but it took me a good hour to get any media working.

    data.append("image", {
      name: "some_name", // also, won't work without this. A name is required
      height: image.height,
      width: image.width,
      type: "multipart/form-data", // <-- this part here
      uri:
        Platform.OS === "android" ? image.uri : image.uri.replace("file:/", "")
    });

@tkserver if your debugger has network inspect enabled, it will override the react-native’s FormData and will result in passing empty FormData object which will look like [Object object] in network inspect. Try making request with turning off network inspect, hope this helps.

@corujoraphael I’m not sure that your code runs as-is. The config where you specify your headers should be an object, but it’s missing a curly brace:

(newData) => {
  const data = new FormData();
  data.append('name', 'raphael');
  data.append('file', {
    uri: newData.image.path,
    type: 'image/jpeg',
    name: 'teste'
  });

  return axios.post(
    `${constants.development.URL_API}/file`,
    data, 
    { 
      headers: {
        'Content-Type': 'multipart/form-data',
      }
    },
  )
}

Since this issue hasn’t received a response and this doesn’t look like an Axios bug based on the info we have, I’m closing this issue.

If you need further assistance debugging your code, please post on Stack Overflow, Gitter, or comment again on this issue.

Thanks!

I have the same issue on react native when I post to a url, as @giladno mentions, you should test in react native and you could verify the error that people report @emilyemorehouse. I report an error 14 days ago https://github.com/axios/axios/issues/1618, but nobody has responded, please describe in the readme of your library that you do not have support for axios on react native, so that many developers do not waste time…!

@duongtranpyco I’ve removed axios from my project, I wrote my own simple class instead, enjoy!

P.S. If you mainly sending JSON, modify the code. In my case, the server usually expects a form.

const request = async ({url, method = 'GET', params, body, responseType = 'json', headers = {}})=>{
    const escape = (data, encode = encodeURIComponent)=>Object.keys(data||{}).reduce((pairs, key)=>{
        for (let value of [].concat(data[key]))
            pairs.push([`${key}`, `${value}`]);
        return pairs;
    }, []).map(pair=>pair.map(encode).join('=')).join('&');

    if (Object.keys(params||{}).length)
        url += '?'+escape(params);
    if (method=='POST' && typeof body=='object')
    {
        if (body instanceof FormData)
            headers['Content-Type'] = 'multipart/form-data';
        else
        {
            body = escape(body);
            headers['Content-Type'] = 'application/x-www-form-urlencoded';
        }
    }
    let {statusCode, request: req} = await new Promise((resolve, reject)=>{
        let xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.withCredentials = true;
        xhr.responseType = {json: 'text'}[responseType]||responseType;
        xhr.onload = ()=>resolve({statusCode: xhr.status, request: xhr});
        xhr.onerror = ()=>reject(new TypeError('Network request failed'));
        xhr.ontimeout = ()=>reject(new TypeError('Network request timed out'));
        for (let key in headers)
            xhr.setRequestHeader(key, headers[key]);
        xhr.send(body||null);
    });
    if (statusCode<200 || statusCode>=400)
        throw new Error(`network request failed with ${statusCode}: ${url}`);
    switch(responseType)
    {
        case 'json':
            return JSON.parse(req.responseText);
        case 'text':
            return req.responseText;
        case 'request':
            return req;
    }
    return req.response;
};

request.get = (url, opt = {})=>request({...opt, url, body: null});
request.post = (url, ...args)=>request({...args[1]||{}, url, method: 'POST', body: args[0]});

If people are still experiencing this issue, and you have GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest; snippet to debug network requests, try adding GLOBAL.FormData = GLOBAL.originalFormData || GLOBAL.FormData it worked for me.

Second @giladno. Since I’m going forward on other parts, I use a workaround instead: write a specific function with fetch() when uploading images.

Tried before and neither stringifying the data or arguments affect the result. The server received the call but no data sent.

XMLHttpRequest

Can you tell me how did you build the request so it uploads properly as multiparty? I keep getting a network error:

Error: Network Error
    at createError (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:168963:17)
    at XMLHttpRequest.handleError (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:168871:16)
    at XMLHttpRequest.dispatchEvent (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28708:27)
    at XMLHttpRequest.setReadyState (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28461:20)
    at XMLHttpRequest.__didCompleteResponse (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28288:16)
    at blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:28398:47
    at RCTDeviceEventEmitter.emit (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:3291:37)
    at MessageQueue.__callFunction (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:2588:44)
    at blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:2345:17
    at MessageQueue.__guard (blob:http://localhost:8081/0754d453-361d-48d1-aaa5-9ff1ad808293:2542:13)

UPDATE: manage to make it work now. Currently using:

formData.append('picture', {
          uri: data.uri,
          name: fname,
          type: 'image/' + ext

        });

I had this problem, but it’s fixed now.

The reason for it was that I was debugging network requests. I had this line of code in my app’s entry point:

GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;

I commented it and it works now.

// IMPORTANT: this will cause FormData requests to fail.
// GLOBAL.XMLHttpRequest = GLOBAL.originalXMLHttpRequest || GLOBAL.XMLHttpRequest;

I did have the some problem in react-native. The problem are not the Headers. In web we can have for example:

let formData = new FormData()
formData.append('key', true // bool value)

but in react native the value for key must be string.

formData.append('key', 'true')

Hi, I am facing the same problem. Has anybody found a solution?

For this case use fetch 😄

var data = new FormData();  
data.append('my_photo', {  
  uri: filePath, // your file path string
  name: 'my_photo.jpg',
  type: 'image/jpg'
}

fetch(path, {  
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'multipart/form-data'
  },
  method: 'POST',
  body: data
});

@emilyemorehouse , I met the same problem using React Native FormData

let s = JSON.stringify({ uri: localUri, name: filename, type: type });
let formData = new FormData();
formData.append('ph0t0', s);

axios.post("http://10.0.1.2:8888/uploadphoto", {
        method: "POST",
        headers: {
                'Content-Type': 'multipart/form-data; charset=utf-8; boundary="another cool boundary";'
        },
        body: formData,
}).then((resp) => {
        console.log(resp);
}).catch(err => {
        console.log(err);
});

Expect some key:value pairs exist in MultipartForm, Form, or PostForm

2018/02/20 18:25:31.740 [W] [photo.go:411] req.MultipartForm: nil 2018/02/20 18:25:31.740 [W] [photo.go:412] req.Form: map[] 2018/02/20 18:25:31.740 [W] [photo.go:413] req. PostForm: map[] 2018/02/20 18:25:31.740 [W] [photo.go:410] req: &{POST /uploadphoto/dialog/57120e8951c643ab42a8c19f/000000000000000000000001 HTTP/1.1 1 1 map[Content-Type:[application/json;charset=utf-8] User-Agent:[okhttp/3.6.0] Accept:[application/json, text/plain, /] Content-Length:[419] Connection:[Keep-Alive] Accept-Encoding:[gzip] Cookie:[lang=zh-TW; PVsessionID=db9a21d63b2d0ea47b68fa8755bd87e2]] 0xc420e3cb80 <nil> 419 [] false 10.0.1.2:8888 map[] map[] <nil> map[] 10.0.1.3:46904 /uploadphoto/dialog/57120e8951c643ab42a8c19f/000000000000000000000001 <nil> <nil> <nil> 0xc420e3cb40} 2018/02/20 18:25:31.740 [E] [photo.go:425] [UploadPhotos] err: request Content-Type isn’t multipart/form-data

Version info axios: 0.16.2 expo: 25.0.0 react: 16.2.0 react-native: 0.52.0