[reactjs] axios post request to send form data

axios POST request is hitting the url on the controller but setting null values to my POJO class, when I go through developer tools in chrome, the payload contains data. What am I doing wrong?

Axios POST Request:

var body = {
    userName: 'Fred',
    userEmail: '[email protected]'
}

axios({
    method: 'post',
    url: '/addUser',
    data: body
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

Browser Response:

enter image description here

If I set headers as:

headers:{
  Content-Type:'multipart/form-data'
}

The request throws the error

Error in posting multipart/form-data. Content-Type header is missing boundary

If I make the same request in postman it's working fine and sets values to my POJO class.

Can anyone explain how to set boundary or how can I send form data using axios.

The answer is


2020 ES6 way of doing

Having the form in html I binded in data like so:

DATA:

form: {
   name: 'Joan Cap de porc',
   email: '[email protected]',
   phone: 2323,
   query: 'cap d\ou'
   file: null,
   legal: false
},

onSubmit:

async submitForm() {
  const formData = new FormData()
  Object.keys(this.form).forEach((key) => {
    formData.append(key, this.form[key])
  })

  try {
    await this.$axios.post('/ajax/contact/contact-us', formData)
    this.$emit('formSent')
  } catch (err) {
    this.errors.push('form_error')
  }
}

Using application/x-www-form-urlencoded format in axios

By default, axios serializes JavaScript objects to JSON. To send data in the application/x-www-form-urlencoded format instead, you can use one of the following options.

Browser

In a browser, you can use the URLSearchParams API as follows:

const params = new URLSearchParams();

params.append('param1', 'value1');

params.append('param2', 'value2');

axios.post('/foo', params);

Note that URLSearchParams is not supported by all browsers (see caniuse.com), but there is a polyfill available (make sure to polyfill the global environment).

Alternatively, you can encode data using the qs library:

const qs = require('qs');

axios.post('/foo', qs.stringify({ 'bar': 123 }));

Or in another way (ES6),

import qs from 'qs';

const data = { 'bar': 123 };

const options = {

method: 'POST',

headers: { 'content-type': 'application/x-www-form-urlencoded' },

data: qs.stringify(data),

url, };

axios(options);


The above method worked for me but since it was something I needed often, I used a basic method for flat object. Note, I was also using Vue and not REACT

packageData: (data) => {
  const form = new FormData()
  for ( const key in data ) {
    form.append(key, data[key]);
  }
  return form
}

Which worked for me until I ran into more complex data structures with nested objects and files which then let to the following

packageData: (obj, form, namespace) => {
  for(const property in obj) {
    // if form is passed in through recursion assign otherwise create new
    const formData = form || new FormData()
    let formKey

    if(obj.hasOwnProperty(property)) {
      if(namespace) {
        formKey = namespace + '[' + property + ']';
      } else {
        formKey = property;
      }

      // if the property is an object, but not a File, use recursion.
      if(typeof obj[property] === 'object' && !(obj[property] instanceof File)) {
        packageData(obj[property], formData, property);
      } else {
        // if it's a string or a File
      formData.append(formKey, obj[property]);
      }
    }
  }
  return formData;
}

In my case, the problem was that the format of the FormData append operation needed the additional "options" parameter filling in to define the filename thus:

var formData = new FormData();
formData.append(fieldName, fileBuffer, {filename: originalName});

I'm seeing a lot of complaints that axios is broken, but in fact the root cause is not using form-data properly. My versions are:

"axios": "^0.21.1",
"form-data": "^3.0.0",

On the receiving end I am processing this with multer, and the original problem was that the file array was not being filled - I was always getting back a request with no files parsed from the stream.

In addition, it was necessary to pass the form-data header set in the axios request:

        const response = await axios.post(getBackendURL() + '/api/Documents/' + userId + '/createDocument', formData, {
        headers: formData.getHeaders()
    });

My entire function looks like this:

async function uploadDocumentTransaction(userId, fileBuffer, fieldName, originalName) {
    var formData = new FormData();
    formData.append(fieldName, fileBuffer, {filename: originalName});

    try {
        const response = await axios.post(
            getBackendURL() + '/api/Documents/' + userId + '/createDocument',
            formData,
            {
                headers: formData.getHeaders()
            }
        );

        return response;
    } catch (err) {
        // error handling
    }
}

The value of the "fieldName" is not significant, unless you have some receiving end processing that needs it.


import axios from "axios";
import qs from "qs";   

const url = "https://yourapplicationbaseurl/api/user/authenticate";
    let data = {
      Email: "[email protected]",
      Password: "Admin@123"
    };
    let options = {
      method: "POST",
      headers: { "content-type": "application/x-www-form-urlencoded" },
      data: qs.stringify(data),
      url
    };
    axios(options)
      .then(res => {
        console.log("yeh we have", res.data);
      })
      .catch(er => {
        console.log("no data sorry ", er);
      });
  };

Upload (multiple) binary files

Node.js

Things become complicated when you want to post files via multipart/form-data, especially multiple binary files. Below is a working example:

const FormData = require('form-data')
const fs = require('fs')
const path = require('path')

const formData = new FormData()
formData.append('files[]', JSON.stringify({ to: [{ phoneNumber: process.env.RINGCENTRAL_RECEIVER }] }), 'test.json')
formData.append('files[]', fs.createReadStream(path.join(__dirname, 'test.png')), 'test.png')
await rc.post('/restapi/v1.0/account/~/extension/~/fax', formData, {
  headers: formData.getHeaders()
})
  • Instead of headers: {'Content-Type': 'multipart/form-data' } I prefer headers: formData.getHeaders()
  • I use async and await above, you can change them to plain Promise statements if you don't like them
  • In order to add your own headers, you just headers: { ...yourHeaders, ...formData.getHeaders() }

Newly added content below:

Browser

Browser's FormData is different from the NPM package 'form-data'. The following code works for me in browser:

HTML:

<input type="file" id="image" accept="image/png"/>

JavaScript:

const formData = new FormData()

// add a non-binary file
formData.append('files[]', new Blob(['{"hello": "world"}'], { type: 'application/json' }), 'request.json')

// add a binary file
const element = document.getElementById('image')
const file = element.files[0]
formData.append('files[]', file, file.name)
await rc.post('/restapi/v1.0/account/~/extension/~/fax', formData)

i needed to calculate the content length aswell

const formHeaders = form.getHeaders();
formHeaders["Content-Length"] = form.getLengthSync()

const config = {headers: formHeaders}

return axios.post(url, form, config)
.then(res => {
    console.log(`form uploaded`)
})

https://www.npmjs.com/package/axios

Its Working

// "content-type": "application/x-www-form-urlencoded", // commit this

import axios from 'axios';

let requestData = {
      username : "[email protected]",
      password: "123456
    };
   
    const url = "Your Url Paste Here";

    let options = {
      method: "POST",
      headers: { 
        'Content-type': 'application/json; charset=UTF-8',

        Authorization: 'Bearer ' + "your token Paste Here",
      },
      data: JSON.stringify(requestData),
      url
    };
    axios(options)
      .then(response => {
        console.log("K_____ res :- ", response);
        console.log("K_____ res status:- ", response.status);
      })
      .catch(error => {
        console.log("K_____ error :- ", error);
      });

fetch request

fetch(url, {
    method: 'POST',
    body: JSON.stringify(requestPayload),           
    headers: {
        'Content-type': 'application/json; charset=UTF-8',
        Authorization: 'Bearer ' + token,
    },
})
    // .then((response) => response.json()) .  // commit out this part if response body is empty
    .then((json) => {
        console.log("response :- ", json);
    }).catch((error)=>{
        console.log("Api call error ", error.message);
        alert(error.message);
});

Check out querystring.

You can use it as follows:

var querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));

Even More straightforward:

axios.post('/addUser',{
    userName: 'Fred',
    userEmail: '[email protected]'
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

In my case I had to add the boundary to the header like the following:

const form = new FormData();
form.append(item.name, fs.createReadStream(pathToFile));

const response = await axios({
    method: 'post',
    url: 'http://www.yourserver.com/upload',
    data: form,
    headers: {
        'Content-Type': `multipart/form-data; boundary=${form._boundary}`,
    },
});

This solution is also useful if you're working with React Native.


Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to react-redux

Local package.json exists, but node_modules missing What is {this.props.children} and when you should use it? axios post request to send form data React-Redux: Actions must be plain objects. Use custom middleware for async actions How do I test axios in Jest? How do I fix "Expected to return a value at the end of arrow function" warning? React-router v4 this.props.history.push(...) not working How to use onClick event on react Link component? How do I add an element to array in reducer of React native redux? How to enable file upload on React's Material UI simple input?

Examples related to axios

How to post query parameters with Axios? Has been blocked by CORS policy: Response to preflight request doesn’t pass access control check How can I add raw data body to an axios request? Axios Delete request with body and headers? Axios having CORS issue Axios handling errors Returning data from Axios API axios post request to send form data Change the default base url for axios Access Control Origin Header error using Axios in React Web throwing error in Chrome

Examples related to ajaxform

axios post request to send form data

Examples related to axios-cookiejar-support

axios post request to send form data