有区别,File是Blob的子类,含name等元数据,传给FormData可自动生成Content-Disposition中的filename;Blob无name,需手动补全或转为File,否则后端可能报“missing filename”。
传 File 对象时,FormData.append('file', file) 会自动生成带 filename="xxx.jpg" 的 Content-Disposition 字段;传 Blob 却不会——哪怕它内容一模一样。后端(比如 Express + multer、Django 的 request.FILES)靠这个字段提取原始文件名,漏了就只能收到 blob 或空名,甚至直接报 “missing filename”。
常见误操作:
file instanceof Blob === true 就以为能混用,结果上传后后端拿不到 originalFilename
canvas.toBlob() 得到一个 Blob,直接塞进 FormData,没补名字也没转 File
formData.append('file', blob, 'report.pdf'),但第三个参数只是 fallback,某些老版 PHP 或 Nginx 配置下不识别new File() 构造函数第一个参数必须是数组,不是单个 Blob 实例。写成 new File(blob, 'a.png') 会报错:TypeError: Failed to construct 'File': parameter 1 is not of type 'sequence'。
正确写法:
立即学习“前端免费学习笔记(深入)”;
const file = new File([blob], 'avatar.png', { type: blob.type });
注意点:
[blob] 是必须的,哪怕只包一个元素type 建议显式传入,别依赖浏览器从扩展名推断(比如你传 'avatar.jpg' 但 blob.type 是 'image/png',后端 MIME 校验可能失败)blob 来自 canvas.toBlob(),记得等 Promise resolve 后再构造,否则 blob 是 undefined
URL.createObjectURL(blob) 生成的 URL 能用于 <img>、<iframe>、<video>,但浏览器完全按 blob.type 解析内容,不看文件扩展名。
典型问题:
new Blob([str], {type: 'text/html'}),再用 <iframe src="blob:xxx"> 加载 → HTML 解析失败,页面空白image/jpg(错误类型),应为 image/jpeg;IE/Edge 旧版除外text/plain 导致乱码,得写 text/plain;charset=utf-8
blob.type 为空字符串(比如忘了传 options),<img> 可能不渲染,fetch 上传也可能被后端拒收URL.createObjectURL() 会在内存中保留对 Blob 的引用,不手动释放就会泄漏。在 React/Vue 列表渲染缩略图、或富文本编辑器插入临时附件时特别危险。
关键规则:
createObjectURL 后,对应组件卸载或替换预览时,必须调用 URL.revokeObjectURL(url)
Blob 多次调用 createObjectURL——返回的 URL 不同,但底层共享同一份内存;revoke 其中一个,所有 URL 都失效File 和 Blob 都适用这条规则,和类型无关真实容易被忽略的是:Canvas 截图后生成的 Blob 默认无名,开发者常直接传给 FormData 或 createObjectURL,既没补 name,也没配对 revoke,上线后内存渐增、上传失败频发,却查不到源头。