Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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: 'Flintstone@gmail.com'
axios({
    method: 'post',
    url: '/addUser',
    data: body
.then(function (response) {
    console.log(response);
.catch(function (error) {
    console.log(error);

Browser Response:

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.

And then add the fields to the form you want to send:

bodyFormData.append('userName', 'Fred');

If you are uploading images, you may want to use .append

bodyFormData.append('image', imageFile); 

And then you can use axios post method (You can amend it accordingly)

axios({
  method: "post",
  url: "myurl",
  data: bodyFormData,
  headers: { "Content-Type": "multipart/form-data" },
  .then(function (response) {
    //handle success
    console.log(response);
  .catch(function (response) {
    //handle error
    console.log(response);

Related GitHub issue:

Can't get a .post with 'Content-Type': 'multipart/form-data' to work @ axios/axios

Your config object is wrong. It should be: { method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } } – Steve Taylor Mar 30, 2019 at 11:20 Latest axios sets the Content-Type header automatically with boundary, so better not mess with it. – user1338062 Sep 26, 2021 at 9:05

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.

This solved my issue when trying to post to imgur's api. Not mentioned anywhere on the docs, but without it you get a 400 Invalid URL response. – Kolby Jan 13, 2019 at 7:14 FormData._boundary is undefined in both Chrome 76 and Firefox 67, and axios deletes the Content-Type header anyway, so this should have no effect. – ash Aug 16, 2019 at 10:18 The boundary part was the only thing that was missing from my code, worked perfeclty in node! – Rafael Moni Sep 24, 2019 at 14:12 _boundary only exists on form-data npm module, not on the native FormData in the Browser! And you should use getBoundary() instead, or better getHeaders(). In the Browser you need only to set ` 'Content-Type': 'multipart/form-data'` without the boundary thing. – Dantio Apr 17, 2021 at 19:21 If you have nested objects in your data, 'querystring' may not work as expected. In that case, you can use 'qs' module to stringify the data. – Zihad Ul Islam Mar 22, 2020 at 5:31 Querystring is deprecated. This is the current method: const data = new URLSearchParams(dataObject).toString(); Then post that data object. – Andrew Taylor May 17, 2022 at 17:41

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)
                    Thank you so much for this example, had a hard time figuring out why multiple file upload was not working.
    – Minkesh Jain
                    Oct 8, 2018 at 5:42
                    I'm not an expert, but in my case I have managed to avoid these complications (concat-stream, async and await) for multiple file upload by using for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) } so I can submit using axios.post(url, formData, config)
    – laimison
                    Aug 2, 2019 at 1:33
                    @TylerLong I can't find any getHeaders method in FormData API. developer.mozilla.org/en-US/docs/Web/API/FormData
    – ankur_rajput
                    May 18, 2020 at 15:12
    
    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);
    const url = "https://yourapplicationbaseurl/api/user/authenticate";
        let data = {
          Email: "testuser@gmail.com",
          Password: "Admin@123"
        let options = {
          method: "POST",
          headers: { "content-type": "application/x-www-form-urlencoded" },
          data: qs.stringify(data),
        axios(options)
          .then(res => {
            console.log("yeh we have", res.data);
          .catch(er => {
            console.log("no data sorry ", er);
    

    I had the similar issues when using FormData with axios to make calls on https://apps.dev.microsoft.com service and it error-red out with "The request body must contain the following parameter: 'grant_type'"

    After reformatting the data from

    grant_type: 'client_credentials', id: '123', secret: '456789'
    "grant_type=client_credentials&id=123&secret=456789"
    

    and the following code worked:

    const config: AxiosRequestConfig = {
        method: 'post',
        url: https://apps.dev.microsoft.com/auth,
        data: 'grant_type=client_credentials&id=123&secret=456789',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
    axios(config)
    .then(function (response) {
      console.log(JSON.stringify(response.data));
    .catch(function (error) {
      console.log(error);
                    You saved me! For some reason building the object with FormData didn't work but when I did something like    data: 'grant_type=client_credentials&id=123&secret=456789', as you suggested it did the trick!
    – thodwris
                    Oct 30, 2021 at 0:37
                    I have to say that indeed this worked! Postman worked with formdata but it didn't on my project. +1
    – Craws
                    Jun 8, 2022 at 8:51
    

    A boundary (which is used, by the server, to parse the payload) is set when the request is sent. You can't obtain the boundary before making the request. So, a better way to get this is using getBoundary() from your FormData.

    var formData = new FormData();
    formData.append('userName', 'Fred');
    formData.append('file0', fileZero);
    formData.append('file1', fileOne);
    axios({
      method: "post",
      url: "myurl",
      data: formData,
      headers: {
          'Content-Type':  `multipart/form-data; ${formData.getBoundary()}`,
      .then(function (response) {
        //handle success
        console.log(response);
      .catch(function (response) {
        //handle error
        console.log(response);
    

    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`)
    

    The 2022 way

    The Axios documentation hasn't updated yet, but there is a convenient way to to make formdata nowadays, by using the axios.toFormData() method.

    Here is its TypeScript definition:

    export function toFormData(sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions): GenericFormData;
    

    Example:

    const formData = axios.toFormData({"myField":"myValue"})
    const response = await axios({
      method: "post",
      url: "...",
      data: formData,
      headers: { ... }
    

    Source:

    You can find the following in Axios's Change log

    [1.0.0] - 2022-10-04

    Added generic TS types for the exposed toFormData helper #4668

    Added enhanced toFormData implementation with additional options 4704

    I needed to upload many files at once using axios and I struggled for a while because of the FormData API:

    // const instance = axios.create(config);
    let fd = new FormData();
    for (const img of images) { // images is an array of File Object
      fd.append('images', img, img.name); // multiple upload
    const response = await instance({
      method: 'post',
      url: '/upload/',
      data: fd
    

    I did NOT specify the content-type: multipart/form-data header!

    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;
                    objectToFormData is undefined and formData is returned outside the for, but is defined inside the for.  formData is easy, but what is objectToFormData  supposed to be?
    – Trevor
                    Dec 11, 2019 at 18:55
                    I think its supposed to be the name of the function. because it's meant to be recursive, so i assume you can change the objectToFormData to packageData or vice versa
    – Raymond Ativie
                    Dec 28, 2019 at 3:29
    

    For me it worked using axios, typescript and form-data(v4.0.0):

    import FormData from "form-data";
    import axios from "axios";
    async function login() {
      var data = new FormData();
      data.append("User", "asdf");
      const return = await axios.post(
        "https://ptsv2.com/t/1q9gx-1652805776/post", data,
        { headers: data.getHeaders() }
      console.log(return);
    

    This should work well when needing to POST x-www-form-urlencoded data using axios from a NodeJS environment. You may need to add an Authorization header to the config.headers object if the endpoint requires authentication.

    const config = {
      headers: {
        accept: 'application/json',
        'cache-control': 'no-cache',
        'content-type': 'application/x-www-form-urlencoded'
    const params = new URLSearchParams({key1: value1, key2: value2});
    return axios
      .post(url, params.toString(), config)
      .then((response) => {
        return response.data;
      .catch((error) => console.error(error));
    

    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.

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

    Its Working

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

    import axios from 'axios';
    let requestData = {
          username : "abc@gmail.cm",
          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),
        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);
    
     transformRequest: [
      function(data, headers) {
        headers["Content-Type"] = "application/json";
        return JSON.stringify(data);
    

    try this, it works