前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库File 与 Blob 的区别
浏览浏览器文件与多媒体

File 与 Blob 在浏览器中有什么本质区别,什么时候不能只按 Blob 处理?

File 是带文件名、修改时间等元数据的特殊 Blob,凡接受 Blob 的 API 都能直接接收 File;只有需要这些文件元数据时,才必须保留 File 类型而不能降级为普通 Blob。

前端进阶之旅 · 一题精讲更新于 2026.09.05
浏览器#文件与多媒体
先看核心答案
理解线索

File 是带文件元数据的 Blob

  1. 继承关系File.prototype 继承自 Blob.prototype。
  2. 独有属性name、lastModified、webkitRelativePath。
  3. 二进制本质两者都代表不可变的原始二进制数据。

只要逻辑需要文件名或修改时间,就必须保留 File 类型,否则可视为 Blob。

核心回答

先记住这个答案

File 接口继承 Blob,并增加 name、lastModified、webkitRelativePath 属性。Blob 只表示不可变二进制数据,无文件名;File 在承载字节之外附带文件元数据,通常来自用户选择的文件或拖拽,也可用 new File() 由脚本构造。因此,多数接受 Blob 的 API(如 FileReader、URL.createObjectURL、fetch 的 body)也接受 File。但若需读取文件名或修改时间,必须将其当作 File;否则可只按 Blob 处理。

  • File 继承 Blob,是带文件名和修改时间的 Blob。
  • 接受 Blob 的 API 基本都接受 File,但反之不然。
  • 需要元数据或用户文件语义时,不能降级为普通 Blob。

原型链与构造差异

在浏览器中,File 接口直接继承自 Blob,因此 file instanceof Blob 为 true。这意味着任何接受 Blob 作为参数的 Web API,如 FileReader、URL.createObjectURL()、fetch() 的 body 选项,都能直接接收 File 对象。但 Blob 构造函数无法生成 File,你可以通过 new File([blob], name, options) 从任意 Blob 创建 File。

二者显著差异在 type 和尺寸等 Blob 属性之外,File 还带文件源信息:name、lastModified(毫秒时间戳)以及 webkitRelativePath(当从目录上传时)。当浏览器从 <input type=file> 或拖拽生成对象时,它一定是 File;而用户脚本合成二进制时用 new Blob() 得到普通 Blob。判断代码时,先看数据是否需要文件语义:若只关心字节,可用 Blob;若需要文件名或最后修改时间,就必须处理 File。

图片预览与上传:File 不可丢的场景

一个常见页面:用户通过 <input type="file" accept="image/*"> 选择图片,页面用 URL.createObjectURL(file) 预览,随后用 fetch 上传。仅把 file 传给这些 API 不会丢失任何元数据,对象仍是 File;真正的降级发生在用旧内容生成新对象时。假设你构造 const blob = file.slice(0, file.size),则得到的 blob 是 Blob,其 name 为 undefined,上传时后端收到无名文件。这是最常见的降级场景。

正确处理是:需要生成分片或变换内容时,先保留原 File 对象的元数据。例如,若用 file.slice() 做分片上传,每个分片是 Blob,但上传时应在 FormData 中附加原文件名和最后修改时间的字段,或重新构造 new File([分片], file.name, { type: file.type, lastModified: file.lastModified }) 以保留语义。若用 canvas.toBlob() 生成压缩图,得到 Blob,必要时应包装为 File 再上传。否则后端只能收到浏览器给的默认文件名,无法据此识别扩展名或按原始文件名归档。总之,需要文件元数据的任何环节,都不应按纯 Blob 处理。

不要误判 File 与 Blob 的边界

需要注意,某些操作会返回 Blob 而非 File,比如 Blob.slice() 总是返回 Blob,不管原对象是否为 File。因此,如果你从 File 中切出一段并期望它仍是 File,则会丢失 name 等属性。类似地,canvas.toBlob() 的回传也是 Blob,不是 File。在这些分支处,显式检查 value instanceof File 能避免类型误判。

另一个边界是:FileReader.readAsArrayBuffer(file) 或 file.text() 返回结果不携带类型。你无法从 ArrayBuffer 或字符串反向推断出原对象类型,因此若需保留文件元数据,应在进入异步读取之前,把 File 引用和解析结果配套存储,或重建 File。反之,如果不是文件来源而是程序生成的业务数据,使用普通 Blob 即可,不必强行为其命名。除非处理文件上传或展示用户文件,否则 File 的额外字段并无必要,这就是“何时不能只按 Blob 处理”的判断准则。

回答前,多想一步

容易答错的地方

误以为 Blob 就是 File
Blob 是通用二进制容器,File 才是带文件信息的子类。例如 new Blob([data]) 不是 File,没有 name 与 lastModified。只有用户选择的文件、或显式用 new File(...) 构造,才可能具备文件语义。
对 slice 后结果掉以轻心
调用 file.slice(start, end) 产生的是 Blob,不是 File。若之后用 FormData 上传此分片,将失去文件名。正确做法是手动附加原名与修改时间,或使用带参数的 new File() 重新包装。
试着用自己的话回答

面试官还会怎么问?

为什么说 `file instanceof File` 始终是真,但 `blob instanceof File` 不一定?

因为 File 继承 Blob,File 实例也是 Blob 实例。而普通 Blob 不是 File。构造函数继承链决定了 instanceof 的结果。你可以用 obj instanceof File 判断是否包含文件元数据。

何时需要把 blob 包装成 File?

当需要获得文件名或计划用该系统文件语境(如上传、下载时带文件名、或需要 lastModified 参与缓存)时。例如从 canvas 导出的 blob,需要下载时名称为 'image.png',就可转换为 File。若只需 post 二进制内容,可直接 blob。

FileReader 接受 Blob,那 File 也能直接用?

能。FileReader.readAsDataURL(file) 与 readAsArrayBuffer(file) 都会正确处理 File,因为 File 是 Blob。FileReader 只读取字节,不需要文件名,这正是按 Blob 对待的合法场景。

从一道题,走向一组知识

把知识连起来

文件与多媒体

Blob.type 为空时能不能根据内容嗅探类型,浏览器给出什么保证?

File 常带有 MIME 类型,但 Blob.type 可能为空,了解嗅探边界有助于判断是否可依赖 type。

文件与多媒体

URL.createObjectURL 创建的地址为什么要 revokeObjectURL,泄漏会怎样表现?

对 File 或 Blob 调用 createObjectURL 后需 revoke,理解生命周期能避免在文件预览中泄漏内存。

参考资料

  • File

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 原型链与构造差异
  3. 图片预览与上传:File 不可丢的场景
  4. 不要误判 File 与 Blob 的边界
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑