当从浏览器(通过fetch
或XMLHttpRequest
)执行AJAX请求时,运行时知道如何处理某些请求正文格式,并将自动设置适当的Content-type
头。
如果请求体是一个FormData
实例,则Content-type
将被设置为multipart/form-data
,并且还将包括来自数据实例的适当mime分界符令牌。
所有这些示例都将以适当的 mime分界符作为 multipart/form-data
发送数据
const body = new FormData();
body.append("file", fileInput.files[0]);
body.append("foo", "foo");
body.append("bar", "bar");
fetch(url, { method: "POST", body });
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(body);
axios.post(url, body);
如果请求体是一个URLSearchParams
实例,则Content-type
将被设置为application/x-www-form-urlencoded
所有这些示例都将作为application/x-www-form-urlencoded
发送数据
const body = new URLSearchParams({ foo: "foo", bar: "bar" });
fetch(url, { method: "POST", body });
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(body);
axios.post(url, body);
您只需要在打算以特定格式发送字符串数据时手动设置
content-type
,例如
text/xml
、
application/json
等,因为运行时无法从数据中推断出类型。
const body = JSON.stringify({ foo: "foo", bar: "bar" });
fetch(url, {
method: "POST",
headers: {
"content-type": "application/json",
},
body
});
const xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("content-type", "application/json");
xhr.send(body);
关于 Axios
Axios 会自动将传入 data
参数的 JavaScript 数据结构转换为字符串,并将 Content-type
头设置为 application/json
,因此在处理 JSON API 时只需要进行最小配置。
axios.post(url, { foo: "foo", bar: "bar" })
Axios在底层使用XMLHttpRequest
,因此FormData
和URLSearchParams
的规范也适用。
Axios v0.27.1已损坏
这个特定版本的Axios无法使用FormData
进行正确的请求。不要使用它!
Axios v1.0.0+已损坏
这是我的个人意见,但自v1.0.0以来的每个Axios发布都在某种程度上存在根本性的问题。我不能建议任何人出于任何原因使用它。
更好的替代方案包括:
- Fetch API(也可在Node v18+中使用)
- got 用于Node.js
- ky 用于浏览器
NodeJS
当从后端使用Axios时,它将无法从FormData
实例推断出Content-type
头。您可以使用请求拦截器解决此问题。
axios.interceptors.request.use(config => {
if (config.data instanceof FormData) {
Object.assign(config.headers, config.data.getHeaders());
}
return config;
}, null, { synchronous: true });
或者在发出请求时直接合并头部信息
axios.post(url, body, {
headers: {
"X-Any-Other-Headers": "value",
...body.getHeaders(),
},
});
请查看 https://github.com/axios/axios#form-data
关于jQuery $.ajax()
jQuery的$.ajax()
方法(以及像$.post()
这样的便捷方法)默认将请求体负载发送为application/x-www-form-urlencoded
。除非告诉它不要这样做,否则JavaScript数据结构将自动使用jQuery.param()进行序列化。如果您希望浏览器根据正文格式自动设置Content-type
头,则还需要在选项中进行配置。
const body = new FormData()
body.append("foo", "foo")
body.append("bar", "bar")
$.ajax({
url,
method: "POST",
data: body,
contentType: false,
processData: false
})
formData
。如果我在组件中像您的回答一样不带header
发布formData
,一切都很好。但是如果我使用dispatch
formData
,Axios
会使用默认头部进行发布:"Content-Type": "application/x-www-form-urlencoded"
。问题可能与Redux
有关。 - ilvthsgmURLSearchParams
和FormData
设置Content-Type
头,请参见此处的第6项。 - Eric Mutta