Firefox downloading multiple files at once not possible?
Asked Answered
I

1

-1

Downloading multiple blobs in chrome, edge and IE doesn't seem to be a problem, but on Firefox I'm having the problem that most of the time only the last file or max. 2 of them will be "downloaded". I searched for a "download blob" code and adapted it to download more at once and the issue is reproducible on my machine on latest Firefox version on Windows 10, see JS code below in Firefox.

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);

It seems to work with following change, but the question is what would be the real profesional solution to this?

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);

It also works using 1,2,3ms as parameter with this many files, but with more files it started working with 100ms, with less some of the files would be "eaten" by the browser.

What I suppose is that browsers have a treshhold under they "merge" click or loading events, it's the question now what would this treshhold for each browser be and if there is a better solution than my current approach?

Issiah answered 21/5, 2019 at 19:14 Comment(6)
Weird coincidence? #56245402Albertinaalbertine
do you need to hide the link? you can just call a.remove() to cleanup; you might need a new anchor each file. and you might need a timeout to prevent it from getting backed up.Finsen
The Question lined by @Ry found an answer that seemed helpful to them: #27116248Tamis
@computercarguy: OP is appending to body. it might be the tag recycling though...Finsen
@dandavis, I see that it's not the same situation, now. If it was tag reuse, I'd expect it to pick the first, not last, use of the tag, but different browsers... OP definitely needs to look into it regardless.Tamis
Funny, this similar question says their code works in Firefox and Chrome, but not Edge and IE. Perhaps an amalgam of both would work?Dublin
W
2

What you are trying to do is called a "carpet-bomb".

It consists in flooding the user's disk with a lot of files until it runs out of space.
In itself, the security risk is quite low even though it may lead to a system crash, it's more boring than any dangerous.
But still, there might be some situations where it can lead to unexpected flaw, like it was the case with the "Safari carpet-bomb" attack.
And maybe more importantly, that's rarely a good UX to have loads of files piling up in the downloads folder along with other unrelated files.

So browsers are actually quite open to tamper this issue, and most have some system in place to avoid this.


Now, there are probably a lot of workarounds to these tamper-systems, but I don't feel it's what you need.

You asked "if there is a better solution than [your] current approach", and the answer is a big YES.

If all your files are available to download in a single click, then pack them in a single file to download.

You can do so by generating a zip file from all your Blobs using one of the many zipping library, or even other compression algorithm depending on your target-clients.

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>
Whatley answered 22/5, 2019 at 1:42 Comment(5)
Haha, I am trying to do a carpet bomb, OK! The example is only to show the issue, my real application is a client-side only HTML file without server side which has the constraint or needing to be as small as possible, the zip lib is at least 800kb big, so this is not an option! The normal case would be that only few files are being downloaded, but the issue already happens with 2 and 3 files.Issiah
@Issiah yes, the browser can't tell if you are doing this in a malicious way or not, this is a carpet bomb. And my answer answers the question at hand. If you have some special case that aren't explicitly stated in your question, there is no reason to expect an answer to this question will treat this unknown special case. And even with this special case in mind, the only "professional" way of handling it is the one exposed in this answer. And the minified version of JSZip is only 97KB. Don't know where you saw 800, even the unminifed one is just 366KBWhatley
Ok, the zip of a lib I downlaoded had that size, but yes, I didn't take a look at the content, so thanks for pointing that out.Issiah
I will accept the second part of the answer if you remove the wrong allegation :)Issiah
@Issiah there is no allegation here, that's just the name of what you describe. Once again I didn't say you are doing it in a malicious way, but still, the fact of downloading a lot of files simultaneously is known as a "carpet bomb".Whatley

© 2022 - 2024 — McMap. All rights reserved.