fetch 上传文件应使用 formdata 包裹 file 或 blob 对象,浏览器自动设置 multipart/form-data 及 boundary;避免手动构造二进制流,后端需按字段名解析 multipart 数据。

Fetch 上传文件的二进制流,核心是用 FormData 包裹 File 或 Blob 对象,让浏览器自动设置正确的 Content-Type(multipart/form-data)和边界(boundary),无需手动构造二进制流。
直接用 FormData 上传 File/Blob
这是最常用、最可靠的方式。浏览器会自动处理编码、分隔符和字段名:
- 从
<input type="file">获取File对象(它继承自Blob) - 创建
FormData实例,调用.append(key, file, filename?) - 把
FormData直接传给fetch()的body,不设headers(否则会覆盖自动设置的Content-Type)
示例:
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', async () => {
const file = input.files[0];
if (!file) return;
const formData = new FormData();
formData.append('upload', file, file.name); // 第三个参数可选,用于服务端获取原始文件名
try {
const res = await fetch('/api/upload', {
method: 'POST',
body: formData // ✅ 不要加 headers: {'Content-Type': ...}
});
console.log(await res.json());
} catch (err) {
console.error(err);
}
});
手动构造 Blob 并上传(适合非 input 场景)
当你没有 <input>,而是需要从 canvas、音频流、字符串等生成二进制数据时,可用 Blob:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 用
new Blob([data], {type: 'mime/type'})创建二进制对象 - 仍通过
FormData.append()提交,不要转成ArrayBuffer或手动拼接 multipart - 若需指定文件名(如服务端依赖 filename 解析类型),第三个参数必须传字符串
例如上传 canvas 截图:
const canvas = document.getElementById('myCanvas');
const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
const formData = new FormData();
formData.append('image', blob, 'screenshot.png'); // 显式命名很重要
await fetch('/api/upload', { method: 'POST', body: formData });
不推荐:手动读取 ArrayBuffer + 构造 multipart
虽然技术上可行(用 FileReader 读取 ArrayBuffer,再用模板字符串拼 boundary),但极易出错:
- 边界字符串必须严格匹配请求头中的
boundary=xxx - 换行符必须为
\r\n,不能用\n - 二进制与文本混合时编码易混乱(尤其含中文 filename)
- 失去浏览器对大文件的流式处理能力,可能卡顿或内存溢出
除非有特殊协议约束(如某些嵌入式 API),否则没必要绕过 FormData。
后端接收注意点(辅助理解)
前端用 FormData 上传时,后端需按 multipart/form-data 解析:
- Node.js(Express)需配合
multer或busboy - Python(Flask)用
request.files.get('upload') - PHP 用
$_FILES['upload'] - 关键:字段名(如
'upload')前后端必须一致;filename 若未显式传,部分浏览器可能用'blob'代替
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










