axios发布请求以发送表单数据


203

axios POST请求正在访问控制器上的url,但为我的POJO类设置了空值,当我浏览chrome中的开发人员工具时,有效负载包含数据。我究竟做错了什么?

Axios POST请求:

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

浏览器响应:

在此处输入图片说明

如果我将标头设置为:

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

请求引发错误

发布多部分/表单数据时出错。Content-Type标头缺少边界

如果我在邮递员中发出相同的请求,则效果很好,并将值设置为POJO类。

任何人都可以解释如何设置边界或如何使用axios发送表单数据。

Answers:


327

您可以使用FormData()发布axios数据, 例如:

var bodyFormData = new FormData();

然后将字段添加到您要发送的表单中:

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

如果您要上传图片,则可能需要使用 .append

bodyFormData.append('image', imageFile); 

然后,您可以使用axios post方法(可以相应地对其进行修改)

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

你可以在这里阅读更多


8
bodyFormData.set不是一个函数,我得到了这个错误
Manoj Bhardwaj

10
您需要使用附加而不是设置。
Pratik Singhal

1
@ManojBhardwaj您需要绑定该函数,假设您在提交函数内发出请求时,您需要绑定该函数。例如:-onSubmit = {this.submit(bind(this)}或ex:-在构造函数builder(super){this.submit = this.submit.bind(this);} Submit(){axios({}) ; ...}
Srikanth Gowda

bodyFormData.append也为我工作。不确定为什么set不工作
Im Batman

1
您的配置对象是错误的。应该是:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
Steve Taylor

35

签出querystring

您可以按以下方式使用它:

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

4
在节点环境中,这甚至更好
Jjagwe Dennis,

如果数据中嵌套了对象,则“ querystring”可能无法按预期工作。在这种情况下,您可以使用“ qs”模块对数据进行字符串化。
Zihad Ul Islam

33

就我而言,我必须将边界添加到标题中,如下所示:

const form = new FormData();
    formData.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}`,
        },
    });

如果您正在使用React Native,则此解决方案也很有用。


3
尝试发布到imgur的api时,这解决了我的问题。在文档的任何地方都没有提到,但是没有它,您将收到400个无效的URL响应。
科尔比

1
FormData._boundary在Chrome 76和Firefox 67中均未定义,并且axios仍会删除Content-Type标头,因此这应该无效。
灰烬

1
边界部分是我的代码中唯一缺少的东西,它在节点中表现出色!
拉斐尔·莫尼

您是救生员
凯文·雷德

嗨,虽然这个问题仅适用于android,但您设法使其在iOS设备上起作用了吗?
凯文·雷德

15

上传(多个)二进制文件

Node.js

当您想通过multipart/form-data尤其是多个二进制文件发布文件时,事情变得很复杂。下面是一个工作示例:

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()
})
  • 而不是headers: {'Content-Type': 'multipart/form-data' }我更喜欢headers: formData.getHeaders()
  • 我在上面使用过asyncawait如果您不喜欢它们,可以将它们更改为简单的Promise语句

以下是新增内容:

浏览器

浏览器FormData与NPM包“ form-data”不同。以下代码在浏览器中对我有用:

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)

1
非常感谢您提供此示例,让我很难理解为什么无法上传多个文件。
Minkesh Jain

1
我不是专家,但就我而言concat-stream,通过使用,我已设法避免了多个文件上传的这些麻烦(asyncawait),for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) }因此我可以使用axios.post(url, formData, config)
laimison

@laimison谢谢,它对我有用。我已经更新了答案。
泰勒·朗

@TylerLong我在FormData API中找不到任何getHeaders方法。developer.mozilla.org/zh-CN/docs/Web/API/FormData
ankur_rajput,

9

更直接:

axios.post('/addUser',{
    userName: 'Fred',
    userEmail: 'Flintstone@gmail.com'
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

2
是的,看来,如果没有文件上传,这是最简单的方法。
Akalanka Weerasooriya,

3

在axios中使用application / x-www-form-urlencoded格式

默认情况下,axios将JavaScript对象序列化为JSON。要改为以application / x-www-form-urlencoded格式发送数据,可以使用以下选项之一。

浏览器

在浏览器中,可以如下使用URLSearchParams API:

const params = new URLSearchParams();

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

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

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

请注意,并非所有浏览器都支持URLSearchParams(请参见caniuse.com),但是有可用的polyfill(确保对全局环境进行polyfill)。

另外,您可以使用qs库对数据进行编码:

const qs = require('qs');

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

或以其他方式(ES6),

从'qs'导入qs;

const data = {'bar':123};

const options = {

方法:“ POST”,

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

数据:qs.stringify(data),

url,};

axios(选项);


3

2020年ES6的运作方式

在html中有表单,我绑定了数据,如下所示:

数据:

form: {
   name: 'Joan Cap de porc',
   email: 'fake@email.com',
   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')
  }
}

1

上面的方法对我有用,但是由于这是我经常需要的东西,因此我对平面对象使用了一种基本方法。注意,我也在使用Vue而不是REACT

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

在我遇到带有嵌套对象和文件的更复杂的数据结构之前,这对我一直有效

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是未定义的,并且formData是在for外部返回的,但在for内部定义的。formData很简单,但是objectToFormData应该是什么?
Trevor

我认为它应该是函数的名称。因为它是递归的,所以我认为您可以将objectToFormDatato 更改为- packageData或反之亦然
Raymond Ativie 19/12/28

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

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),
      url
    };
    axios(options)
      .then(res => {
        console.log("yeh we have", res.data);
      })
      .catch(er => {
        console.log("no data sorry ", er);
      });
  };
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.