在Firefox中,Blob createObjectURL下载不起作用(但在调试时可以工作)

61

我遇到了一个奇怪的问题,下面的函数是我根据在网上找到的关于如何在客户端上创建一个Blob对象并且可以下载其中包含的一些二进制数据的方法(通过传递一个数组)而创建的。这个方法在Chrome浏览器中非常有效,但在Firefox浏览器中却没有任何反应 - 除非我进行调试并逐步执行代码。是的,奇怪的是,如果我在函数内部创建一个断点并逐步执行它,a.click()方法就会弹出下载窗口!

function downloadFile(filename, data) {

    var a = document.createElement('a');
    a.style = "display: none";  
    var blob = new Blob(data, {type: "application/octet-stream"});
    var url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);    
}

有人能帮助我吗?这是使用Firefox 38.0.5测试的。


19
在 Firefox 中,调用 document.body.appendChild(a); 确实是必要的,有点奇怪。 - Dionysios Arvanitis
可能是重复的问题,与 https://dev59.com/2pjga4cB1Zd3GeqPEAOk#43898188 相似。 - andreasonny83
撤销 revokeObjectURL 真的有必要吗? - David
3个回答

91

你可能在太早地删除资源,尝试延迟删除。

    ...
    a.click();
    setTimeout(function(){
        document.body.removeChild(a);
        window.URL.revokeObjectURL(url);  
    }, 100);  
}

我曾经遇到过一个类似的问题,即在 Worker 中创建的 Blob Object URL 在关闭 Worker 后被隐式撤销。你的答案让我找对了方向,在关闭 Worker 之前添加一个超时定时器解决了这个问题。谢谢! - meyertee
4
想要指出的是,据我所知,从延迟“0”开始同样有效- Firefox只需要一个提示,表明您正在做的事情可以放到调用栈的末尾,实际持续时间似乎并不重要。 - Jon z
很奇怪,这并不是我的问题,但我必须在将锚点附加到文档之前添加延迟,尽管主要是通过您的想法使其工作。 - downhand

12

1
document.body.appendChild(newAElement); 对我也起作用。 - David Faure

4
这个解决方案对于我来说在Chrome和Firefox中都适用,可以下载二进制文件。
window.URL = window.URL || window.webkitURL;

var blob = new Blob([new Uint8Array(binStream)], {type: "octet/stream"});

var link = document.getElementById("link");
link.href = window.URL.createObjectURL(blob);

我使用了你的示例,它可以正常工作: var link = document.getElementById("link"); link.href = window.URL.createObjectURL(response); link.download = filename; link.click(); - ticky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接