readasarraybuffer 读大文件会内存暴涨,应分片处理;优先 slice 小范围读取头部信息;及时释放引用;arraybuffer 需转 blob 才能用于 url 或 fetch;注意编码与视图安全使用。

readAsArrayBuffer 读取大文件时内存暴涨
直接调用 readAsArrayBuffer 会把整个文件一次性加载进内存,哪怕是一个 500MB 的视频文件,也会触发浏览器内存警告甚至崩溃。这不是 bug,是设计使然 —— 它返回的是完整的 ArrayBuffer,没有流式分块机制。
实操建议:
- 对大于 10MB 的文件,优先考虑
File.slice()分片 + 多次readAsArrayBuffer,自己拼接逻辑(注意ArrayBuffer不能直接拼,要用Uint8Array视图 +set()) - 若只需校验或解析头部(如 PNG 签名、MP4 moov),只 slice 前 16–64KB 就够,避免全量读取
- 监听
onload后立即释放引用:reader.onload = null; reader = null;,防止闭包意外保留 ArrayBuffer
readAsArrayBuffer 与 readAsDataURL 的性能差异
readAsArrayBuffer 返回原始二进制,readAsDataURL 返回 base64 编码字符串 —— 后者体积膨胀约 33%,且编码过程额外消耗 CPU。但关键区别在于:base64 字符串可直接赋值给 img.src 或 fetch(),而 ArrayBuffer 需转成 Blob 或 Uint8Array 才能用于网络请求或渲染。
常见错误现象:
- 误把
reader.result(ArrayBuffer)直接传给URL.createObjectURL()→ 报错 “Failed to execute 'createObjectURL' on 'URL': Overload resolution failed” - 想用
fetch()上传,却传了 ArrayBuffer 而不是new Blob([arrayBuffer], {type: '...'}) - 用
TextDecoder解码 ArrayBuffer 时没指定正确编码(如 UTF-8),导致乱码 —— 二进制文件不适用 TextDecoder
监听 readAsArrayBuffer 的错误和中断
FileReader 没有超时机制,也没有进度事件,onerror 只在底层读取失败时触发(如文件被删除、权限拒绝),而用户手动调用 reader.abort() 会触发 onabort,但不会抛异常。
使用场景中容易忽略的点:
-
reader.error在onerror回调里才有效,直接访问可能为null - 多次调用
readAsArrayBuffer会自动 abort 前一个操作,但旧的onload仍可能异步执行(竞态),务必在回调开头加if (reader.readyState !== FileReader.DONE) return - 移动端 Safari 对大于 500MB 的文件可能静默失败(无 error,也无 load),需配合
file.size做前置拦截
ArrayBuffer 转 typed array 的安全写法
reader.result 是 ArrayBuffer,但多数操作需要 Uint8Array、DataView 等视图。直接 new Uint8Array(reader.result) 是安全的,但要注意:
- 如果后续要修改内容,必须确保 ArrayBuffer 未被其他视图锁定(一般无问题)
- 不要用
JSON.stringify(new Uint8Array(...))打印 —— 会输出空对象,改用Array.from(uint8Arr)或循环打印前 20 个字节 - 处理音频/图像元数据时,优先用
DataView(支持不同字节序和偏移读取),比如dv.getUint32(4, false)读 BE 格式长度字段
真正麻烦的是跨域 Blob 或 response.arrayBuffer() 场景 —— 那些 ArrayBuffer 可能不可扩展,slice() 后再构造视图更稳妥。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











