FileReader.readAsArrayBuffer卡住或返回null,主因是未正确设置onload/onerror、复用reader实例、或文件对象失效;必须新建FileReader、先绑定事件再调用readAsArrayBuffer。

FileReader.readAsArrayBuffer 读取文件时卡住或返回 null
直接调用 readAsArrayBuffer 后没触发 onload,或者 event.target.result 是 null,大概率是没正确监听事件或文件对象已失效。File 对象本身不是 ArrayBuffer,必须经 FileReader 异步转换。
关键点:不能在 input 的 change 回调里直接取 file.arrayBuffer()(那是 Promise 方法,仅在现代浏览器且需 await);老式写法必须靠 FileReader。
-
FileReader实例不能复用,每次读新文件都要新建 - 务必在调用
readAsArrayBuffer(file)之前 设置onload和onerror - 不要对同一个
File对象反复调用readAsArrayBuffer,会报InvalidStateError
const input = document.querySelector('input[type="file"]');
input.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (e) => {
const buffer = e.target.result; // 类型是 ArrayBuffer
console.log(buffer.byteLength); // ✅ 正确拿到字节长度
};
reader.onerror = () => console.error('读取失败');
reader.readAsArrayBuffer(file); // ✅ 必须放最后
});
想用 async/await 写更简洁?注意 browser 兼容性
file.arrayBuffer() 是 File 原生方法,返回 Promise,但只在 Chrome 83+、Firefox 79+、Safari 14.1+ 支持。IE 完全不支持,旧 Edge(
如果你的项目明确不支持 IE / 旧 Edge,可以用更直观的写法:
立即学习“前端免费学习笔记(深入)”;
input.addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
try {
const buffer = await file.arrayBuffer(); // ✅ 返回 ArrayBuffer
processBytes(buffer);
} catch (err) {
console.error(err.name === 'NotReadableError' ? '文件不可读' : err);
}
});
- 错误类型可能是
NotReadableError(如文件被其他进程锁定)或SecurityError(跨域 blob) - 不建议在
file.arrayBuffer()外再套一层new Response(file).arrayBuffer(),徒增开销且无必要 - 若需兼容 IE,只能退回 FileReader 方案
读到 ArrayBuffer 后怎么处理二进制数据?别直接当字符串用
ArrayBuffer 是原始内存块,没有“内容”概念;直接 String(buffer) 或 JSON.stringify(buffer) 得到的是 [object ArrayBuffer],毫无意义。
真正要操作数据,得配合视图(View):
- 读结构化数据(如 PNG 头、WAV 采样)→ 用
Uint8Array或DataView - 需要按字段解析(如 int32、float64)→ 优先选
DataView,避免字节序陷阱 - 纯字节检查(如魔数)→
new Uint8Array(buffer)最快
const uint8 = new Uint8Array(buffer);
if (uint8[0] === 0x89 && uint8[1] === 0x50) {
console.log('可能是 PNG');
}
const dv = new DataView(buffer);
const width = dv.getUint32(16, false); // offset=16, littleEndian=false
大文件上传时 ArrayBuffer 占内存,小心 OOM
读完整个文件到内存生成 ArrayBuffer,等于把文件 1:1 拷贝进 JS 堆。100MB 文件 ≈ 100MB ArrayBuffer,加上视图引用,极易触发内存警告甚至页面崩溃,尤其在低端 Android 设备上。
- 非必要不一次性读全:改用
slice()分块读(file.slice(start, end)返回新 Blob) - 服务端支持流式上传时,优先用
fetch+ReadableStream(Chrome/Firefox 支持,Safari 有限) - 如果只是校验哈希或抽帧,用 Web Crypto API 的
digest()流式计算,避免落地 ArrayBuffer
最易被忽略的一点:即使你用完 ArrayBuffer,V8 不会立刻释放它——除非显式解除所有引用(包括闭包里的、全局变量存的、未 resolve 的 Promise),否则 GC 可能延迟几秒甚至更久。



















