FireFox 4.0/5.0中FileReader.readAsArrayBuffer报错求助
解决Firefox 4/5中
readAsArrayBuffer报错的问题 我之前在维护需要兼容极旧Firefox版本的项目时,正好碰到过这个一模一样的坑!虽然MDN文档标注readAsArrayBuffer从Firefox 3.6就开始支持,但实际在4.0和5.0版本里,这个API存在两个关键的兼容性问题:
可能的原因
- Blob切片与FileReader的配合bug:早期Firefox的
mozSlice(当时的Blob切片方法)和readAsArrayBuffer组合使用时,会出现无法正确读取数据的情况,尤其在处理大文件切片时。 - API实现不完整:Firefox 4/5的
readAsArrayBuffer虽然存在,但对ArrayBuffer的返回处理有缺陷,偶尔会抛出未明确的错误。
解决方案
方案1:降级到readAsBinaryString并手动转换为ArrayBuffer
这是最稳妥的兼容方式,因为readAsBinaryString在旧Firefox版本里稳定性更高,我们可以把读取到的二进制字符串手动转换成ArrayBuffer:
files.forEach(function(f) { if (window.File && window.FileReader && window.FileList && window.Blob) { var r = new FileReader(); var blobslice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice; var hash = md5.create(); var chunksize = 10 * 1024 * 1024; var start = 0; function readNextChunk() { if (start >= f.size) { // 所有切片处理完成,输出结果 console.log('最终Hash:', hash.toString()); return; } var end = Math.min(start + chunksize, f.size); var blob = blobslice.call(f, start, end); r.onload = function(e) { // 将二进制字符串转为ArrayBuffer var binaryStr = e.target.result; var buffer = new ArrayBuffer(binaryStr.length); var uint8View = new Uint8Array(buffer); for (var i = 0; i < binaryStr.length; i++) { uint8View[i] = binaryStr.charCodeAt(i) & 0xff; } // 更新hash hash.update(uint8View); // 处理下一个切片 start = end; readNextChunk(); }; r.readAsBinaryString(blob); } // 开始处理文件 readNextChunk(); } });
方案2:添加API特性检测并做 fallback
如果想优先使用readAsArrayBuffer,可以先检测API是否能正常工作,不行再降级到readAsBinaryString:
function canUseReadAsArrayBuffer() { const reader = new FileReader(); return typeof reader.readAsArrayBuffer === 'function'; } // 在你的文件处理逻辑中 if (canUseReadAsArrayBuffer()) { r.readAsArrayBuffer(blob); r.onload = function(e) { hash.update(new Uint8Array(e.target.result)); // 后续逻辑... }; } else { // 使用方案1中的二进制字符串转ArrayBuffer逻辑 r.readAsBinaryString(blob); // ... }
额外注意点
- 避免并发读取切片:旧版本Firefox的FileReader对异步操作的支持不好,不要用
forEach同时发起多个读取请求,改用递归逐个处理切片,避免资源冲突。 - 确认切片参数正确:
mozSlice的参数是(start, end),和现代标准一致,但要确保end不超过文件大小,否则可能导致读取失败。
内容的提问来源于stack exchange,提问作者Sjn19
相关产品推荐
相关产品推荐

