题干与适用场景
你要在浏览器中上传大文件并计算摘要。新浏览器支持 Blob.bytes(),但旧浏览器可能不支持。请设计读取、分片、回退、取消、错误处理和兼容性验证方案。
MDN 将 Blob.bytes() 标为 Baseline 2026:它返回一个 Promise,最终得到包含 Blob 内容的 Uint8Array,并可在 Web Worker 使用。题目重点是 API 语义和资源边界,不是把“支持新 API”当成完整上传方案。
面试官考察点
- 能否准确说明
bytes()返回 Promise 和Uint8Array,避免把它当成流。 - 能否识别整 Blob 读取带来的内存峰值,并设计分片或流式路径。
- 能否提供特性检测与
arrayBuffer()、stream()等回退,而不是按浏览器名称判断。 - 能否处理取消、重试、摘要状态、Worker 通信和用户反馈。
- 能否用兼容性矩阵与大文件压力测试证明方案可用。
需要澄清的问题
- 文件大小上限、并发上传数、目标浏览器和是否支持 Web Worker 是什么?
- 摘要算法、服务端分片协议、断点续传和重复块去重如何定义?
- 上传前必须得到完整摘要,还是可以边读边上传并最终校验?
- 失败后是否允许从已确认的块恢复,服务端如何保证幂等?
- 用户切换页面、关闭标签或设备内存紧张时,任务如何停止并恢复?
API 语义与读取路径
Blob.bytes() 不接收参数,返回 Promise;成功值是 Uint8Array,失败时 Promise reject。它会把 Blob 内容作为连续字节数组交给调用方,因此不能据此宣称零拷贝或无限制处理大文件。小文件可在 Worker 中读取并计算摘要,大文件应优先使用 slice() 切块,再对每块读取并上传。
先做能力检测,再选择路径:支持时使用 bytes(),否则使用 arrayBuffer() 转为 Uint8Array;如果目标浏览器和协议允许,使用 stream() 逐块消费。回退代码应保持相同的块编号、摘要输入和错误契约,不能因旧 API 改变服务端校验。
内存、分片与摘要
把整份 Blob 读入内存的峰值至少与文件大小同量级,还要加上上传缓冲、解码和运行时开销。按固定或自适应大小调用 slice(start, end),每次只保留当前块和有限的上传队列。摘要器要按顺序接收块;并行上传不能改变摘要输入顺序。
每块带文件 ID、版本、块序号、长度和内容摘要。服务端以文件 ID 加块序号幂等写入,最终按顺序合并并校验总长度与整文件摘要。块摘要不能替代端到端摘要,因为块丢失、重排或错误拼接仍可能形成错误文件。
取消、重试与 Worker
使用 AbortController 把取消信号传给读取和上传请求;取消后清空待上传队列并释放引用。重试只针对可恢复错误,使用指数退避和幂等块键;认证失效应暂停并重新授权,不应无限重试。Worker 负责摘要计算时,主线程只接收进度、错误和最终结果,避免把整个字节数组复制回主线程。
如果采用 stream(),要遵守背压,读取器速度不能超过网络和摘要器处理能力。任何路径都要记录已确认块数、读取耗时、上传耗时、重试次数、取消原因和峰值内存估计,但日志不得包含文件内容或敏感路径。
兼容性与安全边界
特性检测应检查 typeof Blob !== "undefined" 以及 "bytes" in Blob.prototype,再进入 bytes() 路径。不要仅根据 User-Agent 判断。旧浏览器回退到 arrayBuffer() 或受控的 FileReader,并在不满足内存预算时明确提示用户。
客户端摘要只能用于完整性校验,不能替代服务端授权、病毒扫描和内容类型验证。服务端必须限制文件大小、块大小、块序号范围和总时长;客户端传来的 MIME 类型不可直接作为安全判断。跨 Worker 传输时避免复制敏感内容,完成后尽快释放引用。
失败演练与验证清单
覆盖支持与不支持 bytes() 的浏览器、Web Worker 和主线程、空文件、单块文件、跨块文件、超大文件、网络中断、取消后恢复、重复块、顺序错乱和摘要不匹配。压力测试记录 p95 读取时间、上传吞吐、峰值内存、长任务、失败率和恢复时间。
若 bytes() reject,保留块状态并切换到明确回退;若回退也超出内存预算,停止任务并说明下一步,而不是强行读取整文件。若服务端发现块摘要或总摘要不匹配,丢弃未确认合并结果并允许从最后一致块恢复。
延伸追问与参考答案
bytes() 和 arrayBuffer() 应如何选择?
两者都可能把完整 Blob 内容读入内存;bytes() 直接给出 Uint8Array,适合需要字节视图的代码,但没有自动获得流式处理能力。大文件应优先分片或流式方案。
为什么不能只做客户端整文件摘要?
整文件摘要无法证明服务端按正确顺序收到所有块,也不能替代授权与内容安全检查。应同时验证块序号、块摘要、总长度和服务端最终摘要。
如何验证旧浏览器回退?
用能力检测强制覆盖支持和不支持路径,配合真实浏览器矩阵、Worker/主线程、内存压力、断网恢复和取消测试;不能只在一台新浏览器上验证。