Skip to content

Axios don't send form data in react-native #1321

@corujoraphael

Description

@corujoraphael

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',
       },
   })`

Activity

pedpess

pedpess commented on Jan 30, 2018

@pedpess

@corujoraphael Out of curiosity, was this request working earlier?

emilyemorehouse

emilyemorehouse commented on Feb 11, 2018

@emilyemorehouse
Member

@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!

Ernie6711

Ernie6711 commented on Feb 20, 2018

@Ernie6711

@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 419 [] false 10.0.1.2:8888 map[] map[] map[] 10.0.1.3:46904 /uploadphoto/dialog/57120e8951c643ab42a8c19f/000000000000000000000001 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

giladno

giladno commented on Mar 9, 2018

@giladno

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

emilyemorehouse

emilyemorehouse commented on Mar 9, 2018

@emilyemorehouse
Member

If someone can provide a reproducible example, I'm happy to open this back up.

@Ernie6711 it looks like you have an error in your code -- I don't think you should stringify the file data before appending it to your form data. Also, the arguments for axios.post are axios.post(url[, data[, config]])

Here's an example based on your code:

const file ={ uri: localUri, name: filename, type: type};
const formData = new FormData();
formData.append('file', s);

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

axios.post("http://10.0.1.2:8888/uploadphoto", formData, config).then((resp) => {
        console.log(resp);
}).catch(err => {
        console.log(err);
});
giladno

giladno commented on Mar 9, 2018

@giladno

@emilyemorehouse please check wireshark traces. The data is uploaded but it does NOT use proper form-data encoding. The above example can reproduce the problem. Again - the request is being sent successfully but is it badly encoded.

POST /myserver HTTP/1.1
Content-Type: multipart/form-data

_parts=USERX%2Cusername&_parts=FILE1%2C%5Bobject%20Object%5D
emilyemorehouse

emilyemorehouse commented on Mar 9, 2018

@emilyemorehouse
Member

I have a local client and server example for file uploads, albeit outside of the React Native environment, that works and is properly encoded. The example above isn't really reproducible since it relies on variables and a server that I don't have access to.

My guess is that if there's something incorrect with the upload, it's because the data appended to the form data object is not valid.

giladno

giladno commented on Mar 9, 2018

@giladno

@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...

duongtranpyco

duongtranpyco commented on Mar 16, 2018

@duongtranpyco

I got the same, Axios does not on react native

giladno

giladno commented on Mar 17, 2018

@giladno

@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]});
jlariza

jlariza commented on Apr 19, 2018

@jlariza

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

Ernie6711

Ernie6711 commented on Apr 20, 2018

@Ernie6711

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.

jlariza

jlariza commented on Apr 24, 2018

@jlariza

@Ernie6711 apparently the headers are corrupted and that is why the server is unable to accept the form data. I implemented the workaround with fetch() and it worked with no problems.

20 remaining items

cesar3030

cesar3030 commented on Aug 5, 2019

@cesar3030

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'
})
mkhoussid

mkhoussid commented on Aug 26, 2019

@mkhoussid

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:/", "")
    });
AravindhNextbrain

AravindhNextbrain commented on Dec 3, 2019

@AravindhNextbrain

Hi, I am trying to file Axios upload in Vue.Js. Can anyone review and explain the issue?

In Html
<input type="file" id="file" ref="file" multiple @change="assignFiles"/>

In Js

` assignFiles(e){

      let uploadedFiles = this.$refs.file.files;
      for( var i = 0; i < uploadedFiles.length; i++ ) { 
        this.form.AttachmentDocs.push(uploadedFiles[i]);           
      }
      console.log(this.form.AttachmentDocs);
 },`

So, while trigger the post, am appending form datas.

`proceedSave(e) {

      e.preventDefault();
      this.$v.$touch();
      if(this.$v.$invalid) {
        return;
      }
    this.showLoading(this.loaderId,true);
      this.postDatas.append('form',JSON.stringify(this.form));
      for( var i = 0; i < this.form.AttachmentDocs.length; i++ ){ 
        let attachment = this.form.AttachmentDocs[i];
        this.postDatas.append('files['+i+']',attachment,attachment.name);           
      }

}`

So In the post, I checked console window header, there its showing

files[0]: (binary)
files[1]: (binary)
files[2]: (binary)
files[3]: (binary)

In My server side i cnt to get the files.

mkhoussid

mkhoussid commented on Dec 3, 2019

@mkhoussid

Might have something to do with

this.postDatas.append('files['+i+']',attachment,attachment.name);  

Try files['+' + i + '+']

azizulhaq800804

azizulhaq800804 commented on Dec 3, 2019

@azizulhaq800804

I have the same issue with fetch api. req.body was empty in node js. Using 'express-formidable' solved the issue. https://www.npmjs.com/package/express-formidable

AravindhNextbrain

AravindhNextbrain commented on Dec 3, 2019

@AravindhNextbrain

Might have something to do with

this.postDatas.append('files['+i+']',attachment,attachment.name);  

Try files['+' + i + '+']

Sry + indicates the concatination, wat is the use of string '+' . It result will be files[+0+]

mkhoussid

mkhoussid commented on Dec 3, 2019

@mkhoussid

I have the same issue with fetch api. req.body was empty in node js. Using 'express-formidable' solved the issue. https://www.npmjs.com/package/express-formidable

Did you include app.use(express.json({ extended: false }));?

mkhoussid

mkhoussid commented on Dec 3, 2019

@mkhoussid

Might have something to do with

this.postDatas.append('files['+i+']',attachment,attachment.name);  

Try files['+' + i + '+']

Sry + indicates the concatination, wat is the use of string '+' . It result will be files[+0+]

Your current code will always result in files[+i+] in your for loop. It will never be files[+0+], files[+1+], files[+2+], etc.

Also, files[+0+] will never exist. Not sure what you are trying to do. You need files[0], files[1], files[2]...? If you're trying to build an object, then you can have files['+0+'], but, again, I'm not sure what you're trying to accomplish.

azizulhaq800804

azizulhaq800804 commented on Dec 5, 2019

@azizulhaq800804

I have the same issue with fetch api. req.body was empty in node js. Using 'express-formidable' solved the issue. https://www.npmjs.com/package/express-formidable

Did you include app.use(express.json({ extended: false }));?
No. However, in formidable I have one issue. Uploaded picture is going to requiest fields. Nothing in request files. Not sure why this is happening.

azizulhaq800804

azizulhaq800804 commented on Dec 5, 2019

@azizulhaq800804

@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]});

I am using this code in my project. I am trying to understand this code. One question, is this line necessary,
for (let value of [].concat(data[key]))? It can be written simply,
pairs.push([${key}, ${data[key]}]);

SumitThinktanker

SumitThinktanker commented on Feb 11, 2020

@SumitThinktanker

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.

Where it is?

genglei01

genglei01 commented on Feb 20, 2020

@genglei01

I also had the problem. It is caused by the file path in android.
const path = utils.isAndroid() ? file://${filePath} : filePath;
And it works ok with implementing as the following

    const formData = new FormData();
    const path = utils.isAndroid() ? `file://${filePath}` : filePath;
    formData.append('Voice', {
      uri: path,
      name: 'test',
      type: 'audio/wav',
    });

    formData.append('Content-Type', 'audio/wav');
     const headers =  {
        'Content-Type': 'multipart/form-data',
      };
    return this._sendRequest(url, 'POST', formData, headers);
Geteasymoveinc

Geteasymoveinc commented on Apr 13, 2020

@Geteasymoveinc
 data.append('file', {
    uri: newData.image.path,
    type: 'image/jpeg',
    name: 'teste'

Use name like : name:'teste.jpeg' and it will work. you need to give format to file otherwise it will not work.
I fixed it by having name:'example.jpeg'

fatihayyildiz

fatihayyildiz commented on May 2, 2020

@fatihayyildiz

After several days trying to upload video with axios, I just give up. RNFetchBlob is better option for uploading files from especially Android. This section is easy to implement

rn-fetch-blob

locked and limited conversation to collaborators on May 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @giladno@Steffi3rd@kodayashi@Khaledgarbaya@tkserver

        Issue actions

          Axios don't send form data in react-native · Issue #1321 · axios/axios