场景
服务器返回文件流,用于下载。前端需要自定义下载文件名,因此需要使用javascript
处理文件流blob
。
异常代码
const reader = new FileReader();
reader.readAsDataURL(res);
reader.onload = (e) => {
// 转换完成,创建一个a标签用于下载
if (e.target) {
const a = document.createElement('a');
a.download = options.fileName || 'download';
a.href = e.target.result;
document.body.appendChild(a);
a.click();
a.remove();
}
}
文件下载时,windows chrome提示如下
image.png
原因分析
reader.readAsDataURL
将blob
转换为Base64
赋值给a
标签, a 标签长度有限制,会被截断,因此地址异常
解决
使用URL.createObjectURL(res)
将blob
转换为一个对象URL用于下载。
正常代码
const url = URL.createObjectURL(res);
const a = document.createElement('a');
a.download = options.fileName || 'download';
a.href = url;
a.onclick = () => {
requestAnimationFrame(() => {
URL.revokeObjectURL(url);
})
}
document.body.appendChild(a);
a.click();
a.remove();
内存管理
在每次调用 createObjectURL()
方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 [URL.revokeObjectURL()](https://developer.mozilla.org/zh-CN/docs/Web/API/URL/revokeObjectURL)
方法来释放。
浏览器在 document 卸载的时候,会自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。
延伸
- a标签最大长度 image
-
Base64 位数和文件大小关系 https://www.yuque.com/hekong/unveqo/vv0yop
-
验证释放ObjectURl的合适时机
网友评论