主题
传输上传数据
文件选择完成后,下一步通常不是直接“把文件变量发出去”,而是先把它组织成请求体。
上传文件时最常见的请求体:FormData
浏览器里最常见的文件上传数据结构是 FormData。
它适合表示:
- 文件字段
- 普通文本字段
- 一组表单项
js
const formData = new FormData()
formData.append('file', file)
formData.append('username', 'exampleUser')为什么文件上传通常不用 JSON
如果请求里带的是二进制文件,直接用 JSON 通常不合适。
文件上传场景里更常见的是:
multipart/form-data
这正是 FormData 最擅长处理的格式。
一个基础例子
js
const fileInput = document.getElementById('fileInput')
const file = fileInput.files[0]
const formData = new FormData()
formData.append('file', file)
formData.append('username', 'exampleUser')
formData.append('email', 'user@example.com')这时同一个请求体里既可以放文件,也可以放普通字段。
可以怎么发送
用 fetch
js
fetch('/upload', {
method: 'POST',
body: formData,
})用 XHR
js
const xhr = new XMLHttpRequest()
xhr.open('POST', '/upload')
xhr.send(formData)一个高频注意点:不要手动设置 Content-Type
这是文件上传里最常见的坑之一。
当请求体是 FormData 时,不要手动写:
js
headers: {
'Content-Type': 'multipart/form-data'
}因为浏览器会自动补完整的 Content-Type,包括必要的 boundary。
如果手动写死,反而可能让服务端无法正确解析。
传统表单提交也是同一类思路
浏览器原生表单上传本质上也是类似模型:
html
<form enctype="multipart/form-data">
<input type="file" name="fileInput" />
<button type="submit">上传文件</button>
</form>区别只是:
- 原生表单由浏览器自动提交
FormData + fetch/XHR更适合前端主动控制流程
什么时候不是 FormData
如果上传的不是文件,而只是普通结构化数据,通常还是优先 JSON:
js
fetch('/api/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'Lee' }),
})所以可以先简单记成:
- 有文件:优先
FormData - 纯业务数据:优先 JSON
使用建议
- 上传文件时,优先用
FormData组织请求体。 - 文件和附加字段可以一起放进同一个
FormData。 - 发送
FormData时,不要手动设置Content-Type。 - 如果只是普通对象数据,不要为了统一而强行改成
FormData。
