【问题标题】:Firefox downloading multiple files at once not possible?Firefox 不能一次下载多个文件?
【发布时间】:2019-10-08 05:55:12
【问题描述】:

在 chrome、edge 和 IE 中下载多个 blob 似乎不是问题,但在 Firefox 上我遇到的问题是大多数时候只有最后一个文件或最大文件。其中 2 个将被“下载”。我搜索了一个“下载 blob”代码并将其调整为一次下载更多内容,并且该问题可以在我的机器上在 Windows 10 上的最新 Firefox 版本上重现,请参阅下面 Firefox 中的 JS 代码。

var saveData = (function () {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, fileName) {
        var json = JSON.stringify(data),
            blob = new Blob([json], {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());

var data = { x: 42, s: "hello, world", d: new Date() },
    fileName = "my-download.json";

saveData(data, fileName);
saveData(data, fileName + 1);
saveData(data, fileName + 2);
saveData(data, fileName + 3);
saveData(data, fileName + 4);
saveData(data, fileName + 5);
saveData(data, fileName + 6);
saveData(data, fileName + 7);

它似乎适用于以下更改,但问题是真正的专业解决方案是什么?

var saveData = (function () {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, fileName) {
        var json = JSON.stringify(data),
            blob = new Blob([json], {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());

var data = { x: 42, s: "hello, world", d: new Date() },
    fileName = "my-download.json";

saveData(data, fileName);
setTimeout(function(){ saveData(data, fileName + 0) }, 1000);
setTimeout(function(){ saveData(data, fileName + 1) }, 2000);
setTimeout(function(){ saveData(data, fileName + 2) }, 3000);

它也可以使用 1,2,3ms 作为参数来处理这么多文件,但是对于更多的文件,它开始使用 100ms,更少的一些文件会被浏览器“吃掉”。

我认为浏览器在“合并”点击或加载事件下有一个阈值,现在的问题是每个浏览器的阈值是多少,是否有比我目前的方法更好的解决方案?

【问题讨论】:

  • 你需要隐藏链接吗?您可以拨打a.remove() 进行清理;您可能需要一个新的锚每个文件。你可能需要一个超时来防止它被备份。
  • @Ry 提出的问题找到了一个对他们似乎有帮助的答案:stackoverflow.com/questions/27115748/…
  • @computercarguy:OP 附加到正文。虽然可能是标签回收......
  • @dandavis,我发现现在情况不一样了。如果是标签重用,我希望它选择标签的第一个,而不是最后一个,但是不同的浏览器......无论如何,OP肯定需要调查它。

标签: javascript html firefox blob


【解决方案1】:

您尝试做的事情被称为“地毯式炸弹”。

它包括用大量文件淹没用户的磁盘,直到空间用完。
就其本身而言,安全风险很低,即使它可能导致系统崩溃,也比任何危险都无聊。
但是,在某些情况下它可能会导致意外缺陷,例如 "Safari carpet-bomb" attack 的情况。
也许更重要的是,在下载文件夹中堆积大量文件以及其他不相关的文件,这很少是一个好的用户体验。

所以浏览器实际上是quite open 来篡改这个问题,并且大多数浏览器都有一些系统来避免这种情况。


现在,这些篡改系统可能有很多变通方法,但我认为这不是您所需要的。

您问“是否有比 [您的] 当前方法更好的解决方案”,答案是肯定的。

如果您的所有文件都可以通过单击下载,则将它们打包到一个文件中以供下载。

您可以通过使用众多压缩库之一从所有 Blob 生成一个 zip 文件来做到这一点,或者甚至是其他压缩算法,具体取决于您的目标客户端。

const blobs = "This is a sample text that will get split in chunks of separate text files"
  .split(' ')
  .map((txt) => new Blob([txt])); 

const zip = new JSZip();
const folder = zip.folder('some-words');

blobs.forEach((blob, i) =>
  folder.file(`a-word_${i}.txt`, blob)
);

zip.generateAsync({type : "blob"})
  .then(zip_blob => {
    dl.href = URL.createObjectURL(zip_blob);
    dl.download = "myfiles.zip";
  });
<!-- using JSZip library https://stuk.github.io/jszip/ -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.2.0/jszip.min.js"></script>
<a id="dl">download</a>

【讨论】:

  • 哈哈,我正在尝试做地毯炸弹,OK!这个例子只是为了说明问题,我的真实应用程序是一个只有客户端的 HTML 文件,没有服务器端,它有限制或需要尽可能小,zip lib 至少 800kb 大,所以这不是选项!正常情况是只下载了几个文件,但问题已经发生在 2 和 3 个文件上。
  • @David 是的,浏览器无法判断您是否以恶意方式执行此操作,这是一个地毯炸弹。我的回答回答了手头的问题。如果您有一些未在问题中明确说明的特殊情况,则没有理由期望该问题的答案会处理这种未知的特殊情况。即使考虑到这种特殊情况,处理它的唯一“专业”方式也是此答案中公开的方式。而 JSZip 的缩小版只有 97KB。不知道你在哪里看到的800,即使是未缩小的也只有366KB
  • 好的,我下载的 lib 的 zip 有这个大小,但是是的,我没有看内容,所以感谢您指出这一点。
  • 如果您删除错误的指控,我将接受答案的第二部分:)
  • @David 这里没有任何指控,这只是您所描述的名称。我再次没有说你是在以恶意的方式这样做,但是,同时下载大量文件的事实仍然被称为“地毯炸弹”。
猜你喜欢
  • 1970-01-01
  • 2019-01-30
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2015-03-04
  • 2018-09-18
  • 2011-01-21
相关资源
最近更新 更多