前端进阶之旅前端进阶之旅
  • 基础篇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 name lastModified 可信边界
浏览浏览器文件与多媒体

为什么不能信任 File.name 与 File.lastModified 做唯一键或新鲜度判断?

File.name 与 lastModified 来自本机元数据,可重名、可伪造、可被修改,无法作为唯一键或新鲜度的可靠依据。

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

文件元数据的可信边界

  1. 来源本机文件系统,非服务器源
  2. 唯一性跨目录可重名,仅凭name无法区分
  3. 可变性用户可改系统时间或属性

只有内容或权威服务器提供的标识才可作为可靠依据。

核心回答

先记住这个答案

File.name 是用户本机文件名,不同目录或不同文件可同名;lastModified 由文件系统时间戳提供,用户可改系统时间或文件属性。两者都未经服务器背书,也不能防篡改。做唯一键需结合内容哈希等不可变特征;做新鲜度判断应依赖服务端返回的 ETag、Last-Modified 或内容校验,而不是客户端元数据。

  • 跨目录可重名,同目录内唯一
  • lastModified 可被时钟或文件 API 修改
  • 唯一键需内容哈希,新鲜度需服务器认可

元数据的产生与局限

File.name 取自用户选择的本地文件路径的末段,操作系统允许同一目录下文件名唯一,但不同目录或不同来源可重名。例如用户从文件夹A和文件夹B分别选择同名报告.pdf,两个 File 对象的 name 都可能是 report.pdf。File.lastModified 来自文件系统时间戳,单位毫秒,可被文件系统或工具改写,且用户系统时钟不准确时,该值可能偏离真实修改时间。

浏览器不对此提供真实性保证。File 是 Blob 的子类,只负责承载二进制数据和基本元数据,其内容可随意构造:new File([...], 'x', { lastModified: 0 }) 可任意指定 lastModified。因此,将这两个字段组合作为唯一键或新鲜度判据,在重复上传、同名校验、缓存更新等场景中会产生误判。

重复上传判定失灵

假设上传组件以 name + lastModified + size 作 key,用来判断用户是否选择了同一文件。用户先上传 /home/a/photo.jpg,该文件 lastModified 为 1610000000000。之后同一文件被复制到 /home/b/photo.jpg,系统可能保留原修改时间,也可能更新为复制时间。若复制更新为 1611000000000,则内容未变导致哈希相同,但 lastModified 不同使得 key 不同,从而误判为新文件。

更常见的是同名不同内容:用户修改 photo.jpg 并另存为同名文件,lastModified 变为新时间。若用同一 key 则视为新文件,这是合理的。但若用户修改后手动改回原时间,则 key 不变,上传逻辑可能跳过。解决方式是读取文件内容并计算 SHA-1 或 SHA-256 指纹,比较哈希而不是元数据,才能可靠去重。

何时可以信赖或需要降级

在单个页面会话中,如果只希望区分不同 File 对象,name 和 lastModified 可作粗略提示,但绝不能用于持久化存储中的唯一键。当文件来自同一目录且用户未修改系统时间时,lastModified 能近似反映修改顺序,但它不精确:毫秒粒度可能不足以区分快速连续修改。

对新鲜度判断,可靠做法是让服务器返回资源版本信息如 ETag,或在上传前计算内容哈希。前端若坚持使用 lastModified,至少应同时记录 size 并验证服务端记录的 lastModified 是否一致,但攻击者仍可通过伪造时间绕过。最终权衡:若需强一致性,必须引入摘要算法;若只是交互提示,可接受误判但应明确标注。

回答前,多想一步

容易答错的地方

lastModified 可靠地反映文件最后保存时间
错误:lastModified 能可靠反映文件的最后保存时间。实际上,文件被移动或复制时时间可能改变,且用户可改系统时钟。真实修改时间由文件系统记录,不可信。依据:File API 只暴露属性,不保证其与服务器或内容同步。
name+lastModified+size 组合足够唯一
错误:相同大小和名字但不同内容的文件很常见,时间戳也可伪造。哈希冲突概率极低,基于内容才可靠。组合只是降低误判率,并不能根除。
试着用自己的话回答

面试官还会怎么问?

那么 File 对象有没有可靠的唯一标识?

没有内建标识。File 对象本身引用一个底层数据块,但不同 File 可共享相同 Blob 数据。要获得唯一标识,需计算内容哈希。但哈希也有碰撞理论上,实际用 SHA-256 已足够安全。

用 lastModified 做缓存新鲜度判断,后端如何配合?

后端可返回 Last-Modified 头,但应同时依赖 ETag 实体标签。前端用内容哈希或 ETag 比较,避免依赖本地时间戳。若本地时钟不准,条件请求可能失效。

如果只是防重复点击上传,不持久化,还需要哈希吗?

不需要。可在上传按钮禁用、或对比 File 对象的 size 和名字简单提示。但若用户选择相同路径文件但内容已变,按钮禁用会阻止重新上传,需要记录 active 状态。哈希开销大但更准确。

从一道题,走向一组知识

把知识连起来

文件与多媒体

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

Blob.type 空时也需要内容嗅探,与不能依赖元数据一样,体现二进制对象的不可信属性。

文件与多媒体

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

File 与 Blob 本质区别在于元数据,但身份识别同样不能依赖 name 和 lastModified。

参考资料

  • File

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

本题目录
  1. 先记住这个答案
  2. 元数据的产生与局限
  3. 重复上传判定失灵
  4. 何时可以信赖或需要降级
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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