如何仅在对象URL's已下载

How can I revoke an object URL only after it's downloaded?

本文关键字:下载 何仅 对象 URL      更新时间:2023-09-26

我使用以下代码在JavaScript中保存一个文件:

var a = document.createElement('a');
a.href = URL.createObjectURL(new Blob(['SOME DATA']));
a.download = 'some.dat';
a.click();

我想在下载文件后撤销URL(使用URL.revokeObjectURL)。什么时候这样做安全?

我可以在调用a.click()后立即撤销它吗(这似乎有效,但我不确定它是否安全)?在a的点击事件监听器中?有没有办法让点击事件监听器在默认操作后运行

DOM元素上的

a.click()模拟点击元素,而不是传播点击事件,因此它直接发送到浏览器。我相信使用计时器将撤销URL对象转移到另一个事件周期会更安全一点:

setTimeout(function() {
 URL.revokeObjectURL(a.href);
}, 0);

经过一些实验,Chrome和Safari似乎都可以下载2GB的文件,只要在单击元素后立即撤销即可。在浏览器开始陷入停顿之前,Firefox能够下载600MB的文件。

这是我用来下载大文件的:

const a = document.createElement('a');
const buffer = new ArrayBuffer(2_000_000_000);
const view = new Uint8Array(buffer);
for(let i=0; i<view.length; i++) {
    view[i] = 255;
}
a.href = URL.createObjectURL(new Blob([buffer]));
a.download = 'some.dat';
a.click();
URL.revokeObjectURL(a.href);

规范中没有特别提到在撤销url时中止现有流,所以理论上这样做是可以的。

然而,为了安全起见,我会使用setTimeout()在几秒钟后撤销url,或者如果下载是从特定屏幕启动的,您可以添加逻辑,在用户离开该屏幕后撤销它。

一旦域的最后一页关闭,浏览器也会自动撤销对象URL,因此根据您的情况,完全不撤销URL可能也是一个可行的解决方案。