如何仅在下载后撤销对象 URL?

Ste*_*out 6 javascript cross-browser bloburls

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

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

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

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

Jes*_*end 6

经过一些实验,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);
Run Code Online (Sandbox Code Playgroud)

该规范没有具体提到在撤销 URL 时中止现有流,因此理论上这样做就可以了。

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

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


Sta*_*olc 5

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

setTimeout(function() {
 URL.revokeObjectURL(a.href);
}, 0);
Run Code Online (Sandbox Code Playgroud)

  • 这样,您可能会在下载文件之前删除该文件。这是一个非常糟糕的建议,绝对不是这个问题的解决方案。 (4认同)