跳到主要内容

Multipart 请求体

multipart/form-data 形式提交数据

使用 FormData API

浏览器

const form = new FormData()
form.append("my_field", "my value")
form.append("my_buffer", new Blob([1, 2, 3]))
form.append("my_file", fileInput.files[0])

axios.post("https://example.com", form)

可以使用内部的 Axios 序列化器和相应的快捷方法达到相同的效果:

axios.postForm("https://httpbin.org/post", {
my_field: "my value",
my_buffer: new Blob([1, 2, 3]),
my_file: fileInput.files // FileList 将被解包为单独的字段
})

HTML 表单可以直接作为请求载荷传递。

Node.js

import axios from "axios"

const form = new FormData()
form.append("my_field", "my value")
form.append("my_buffer", new Blob(["some content"]))

axios.post("https://example.com", form)

由于 Node.js 当前不支持从文件创建 Blob,你可以使用第三方包来实现此目的。

import { fileFromPath } from "formdata-node/file-from-path"

form.append("my_field", "my value")
form.append("my_file", await fileFromPath("/foo/bar.jpg"))

axios.post("https://example.com", form)

对于早于 v1.3.0 的 Axios 版本,你必须导入 form-data 包。

const FormData = require("form-data")

const form = new FormData()
form.append("my_field", "my value")
form.append("my_buffer", new Buffer(10))
form.append("my_file", fs.createReadStream("/foo/bar.jpg"))

axios.post("https://example.com", form)

自动序列化

v0.27.0 开始,Axios 支持在请求的 Content-Type 头设置为 multipart/form-data 时,将对象自动序列化为 FormData 对象。

以下请求将以 FormData 格式提交数据(浏览器和 Node.js):

import axios from "axios"

axios
.post(
"https://httpbin.org/post",
{
user: {
name: "Dmitriy"
},
file: fs.createReadStream("/foo/bar.jpg")
},
{
headers: {
"Content-Type": "multipart/form-data"
}
}
)
.then(({ data }) => console.log(data))

Axios FormData 序列化器支持一些特殊的后缀来执行以下操作:

  • {} - 使用 JSON.stringify 序列化值
  • [] - 将类数组对象解包为具有相同键的单独字段
提示

注意:默认情况下,数组和 FileList 对象将使用解包/展开操作。

FormData 序列化器通过 config.formSerializer: object 属性支持附加选项来处理罕见情况:

  • visitor: Function - 用户定义的访问器函数,将按照自定义规则递归调用,将数据对象序列化为 FormData 对象。

  • dots: boolean = false - 使用点符号而不是括号来序列化数组和对象。

  • metaTokens: boolean = true - 在 FormData 键中添加特殊后缀(例如 user{}: '{"name": "John"}')。后端的 body-parser 可能会使用这些元信息自动将值解析为 JSON。

  • indexes: null|false|true = false - 控制如何将索引添加到 flat 类数组对象的解包键中。

    • null - 不添加括号(arr: 1, arr: 2, arr: 3
    • false(默认)- 添加空括号(arr[]: 1, arr[]: 2, arr[]: 3
    • true - 添加带索引的括号(arr[0]: 1, arr[1]: 2, arr[2]: 3

假设有一个像下面这样的对象:

const obj = {
x: 1,
arr: [1, 2, 3],
arr2: [1, [2], 3],
users: [
{ name: "Peter", surname: "Griffin" },
{ name: "Thomas", surname: "Anderson" }
],
"obj2{}": [{ x: 1 }]
}

Axios 序列化器内部将执行以下步骤:

const formData = new FormData()
formData.append("x", "1")
formData.append("arr[]", "1")
formData.append("arr[]", "2")
formData.append("arr[]", "3")
formData.append("arr2[0]", "1")
formData.append("arr2[1][0]", "2")
formData.append("arr2[2]", "3")
formData.append("users[0][name]", "Peter")
formData.append("users[0][surname]", "Griffin")
formData.append("users[1][name]", "Thomas")
formData.append("users[1][surname]", "Anderson")
formData.append("obj2{}", '[{"x":1}]')
import axios from "axios"

axios
.post(
"https://httpbin.org/post",
{
"myObj{}": { x: 1, s: "foo" },
"files[]": document.querySelector("#fileInput").files
},
{
headers: {
"Content-Type": "multipart/form-data"
}
}
)
.then(({ data }) => console.log(data))

Axios 支持以下快捷方法:postFormputFormpatchForm,它们只是相应的 HTTP 方法,其中 Content-Type 标头预设为 multipart/form-data

FileList 对象可以直接传递:

await axios.postForm(
"https://httpbin.org/post",
document.querySelector("#fileInput").files
)

所有文件将以相同的字段名 files[] 发送。