ChatGPT解决这个技术问题 Extra ChatGPT

axios post请求发送表单数据

axios POST 请求正在访问控制器上的 url,但将 null 值设置为我的 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);
});

浏览器响应:

https://i.stack.imgur.com/FKTOx.png

如果我将标题设置为:

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

请求抛出错误

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

如果我在邮递员中提出相同的请求,它工作正常并将值设置为我的 POJO 类。

谁能解释如何设置边界或如何使用 axios 发送表单数据。

这与 react 和 redux 有什么关系?我们可以把它变成通用的 JS 吗?

N
Nikita Fedyashev

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

var bodyFormData = new FormData();

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

bodyFormData.append('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);
  });

相关的 GitHub 问题:

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


bodyFormData.set 不是函数我收到此错误
您需要使用追加而不是设置。
您的配置对象是错误的。应该是:{ method: 'post', url: 'myurl', data: bodyFormData, headers: {'Content-Type': 'multipart/form-data' } }
在 nodejs 中你需要 npm install --save form-data
最新的 axios 会自动设置 Content-Type 标头与边界,所以最好不要弄乱它。
L
Lajos Mészáros

在我的情况下,我必须将边界添加到标题中,如下所示:

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

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


这解决了我在尝试发布到 imgur 的 api 时的问题。文档中没有提到任何地方,但是没有它,您会收到 400 Invalid URL 响应。
FormData._boundary 在 Chrome 76 和 Firefox 67 以及 axios deletes the Content-Type header anyway 中都未定义,因此这应该无效。
边界部分是我的代码中唯一缺少的部分,在节点中完美运行!
嗨,一个问题虽然这仅适用于 android,但您是否设法使其在 iOS 设备上运行?
@KevinRED 是的,当时我实际上是在将 React Native 与 iOS 应用程序一起使用......
H
Henry Woody

查看querystring

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

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

这在节点环境中甚至更好
如果您的数据中有嵌套对象,“querystring”可能无法按预期工作。在这种情况下,您可以使用“qs”模块对数据进行字符串化。
这不是表单数据。这是一种 url 编码的表单格式。
由于某种原因,querystring 包已被弃用
不推荐使用查询字符串。这是当前方法: const data = new URLSearchParams(dataObject).toString();然后发布该数据对象。
T
Tyler Liu

上传(多个)二进制文件

节点.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()

我在上面使用 async 和 await,如果你不喜欢它们,可以将它们更改为简单的 Promise 语句

为了添加您自己的标头,您只需标头: { ...yourHeaders, ...formData.getHeaders() }

新增内容如下:

浏览器

浏览器的 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)

非常感谢您提供此示例,很难弄清楚为什么多个文件上传不起作用。
我不是专家,但就我而言,我已经设法避免了使用 for(var x = 0; x<this.state.files.length; x++) { formData.append('files[]', this.state.files[x]) } 上传多个文件的这些复杂情况(concat-streamasyncawait),因此我可以使用 axios.post(url, formData, config) 提交
@laimison 谢谢,它对我有用。我已经更新了我的答案。
@TylerLong 我在 FormData API 中找不到任何 getHeaders 方法。 developer.mozilla.org/en-US/docs/Web/API/FormData
headers: formData.getHeaders() 是它为我工作的原因。谢谢。
D
Despertaweb

2020 ES6 做事方式

拥有 html 中的表单,我在数据中绑定如下:

数据:

form: {
   name: 'Joan Cap de porc',
   email: 'fake@email.com',
   phone: 2323,
   query: 'cap d\ou'
   file: null,
   legal: false
},

提交:

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

A
Apostolos

在 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),

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

A
Akalanka Weerasooriya

更直接:

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

是的,看起来,如果没有文件上传,这是最简单的方法。
A
ABHIJEET KHIRE
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);
      });
  };

s
s-hunter

我在将 FormData 与 axios 一起使用以调用 https://apps.dev.microsoft.com 服务时遇到了类似的问题,并且由于“请求正文必须包含以下参数:'grant_type'"

重新格式化数据后

{
  grant_type: 'client_credentials',
  id: '123',
  secret: '456789'
}

"grant_type=client_credentials&id=123&secret=456789"

以下代码有效:

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

你救了我!由于某种原因,使用 FormData 构建对象不起作用,但是当我按照您的建议执行类似 data: 'grant_type=client_credentials&id=123&secret=456789', 的操作时,它就成功了!
我不得不说这确实有效!邮递员使用 formdata,但它不在我的项目中。 +1
c
cenobit

我还需要计算内容长度

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

没有这个,我无法得到回应。谢谢
C
Constantin De La Roche

我需要使用 axios 一次上传许多文件,但由于 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
})

我没有指定 content-type: multipart/form-data 标头!


J
Juan Pablo Ugas

上面的方法对我有用,但因为它是我经常需要的东西,所以我使用了平面对象的基本方法。注意,我也在使用 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 应该是什么?
我认为它应该是函数的名称。因为它是递归的,所以我假设您可以将 objectToFormData 更改为 packageData ,反之亦然
I
ISparkes

就我而言,问题在于 FormData 追加操作的格式需要填写额外的“选项”参数来定义文件名,因此:

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

我看到很多抱怨 axios 坏了,但实际上根本原因是没有正确使用表单数据。我的版本是:

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

在接收端,我正在用 multer 处理这个问题,最初的问题是文件数组没有被填充——我总是收到一个请求,但没有从流中解析出任何文件。

此外,还需要在 axios 请求中传递 form-data 标头集:

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

我的整个函数如下所示:

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

“fieldName”的值并不重要,除非您有一些需要它的接收端处理。


那么浏览器 formData 对象呢? Axios 不适用于浏览器表单数据
A
Andrew Taylor

当需要使用来自 NodeJS 环境的 axios 发布 x-www-form-urlencoded 数据时,这应该可以很好地工作。如果端点需要身份验证,您可能需要将 Authorization 标头添加到 config.headers 对象。

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

N
Nathan Getachew

boundary (服务器使用它来解析负载) 在发送请求时设置。在发出请求之前您无法获得边界。因此,更好的方法是使用 FormData 中的 getBoundary()

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


S
Steven Matthews

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

它的工作

// "content-type": "application/x-www-form-urlencoded", // 提交

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

G
Gururaj H
 transformRequest: [
  function(data, headers) {
    headers["Content-Type"] = "application/json";
    return JSON.stringify(data);
  }
]

试试这个,它有效


B
Bruno Yuzo

对我来说,它使用 axios、typescript 和 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);
}

n
none

nodejs 中,您可以改用 URLSearchParams

像这样:

  const formData = new URLSearchParams({
     param1: 'this',
     param2: 'is',
     param3: 'neat',
});