Search code examples
javascriptblobblobstorage

Why to append blob download link to document body?


I am trying to transform a table to a csv file then download it, but I faced an issue while using Blob to download the csv document. The code snippet I am using to download the csv file is:

    var elem = window.document.createElement('a');
    elem.href = window.URL.createObjectURL(blob);
    elem.download = filename;        
    document.body.appendChild(elem);
    elem.click();        
    document.body.removeChild(elem);

The issue is that the csv file is not downloading with the name I am assigning to the file. It uses a randomly generated name and with no extension. example of the file name after being downloaded: 43af43ac-7491-44ed-a779-a6c8f1972b1a.

I was able to fix this by removing the append() remove() functions. Consequently, I have two questions:

1- Why the issue is happening, and what is the best solution?

2- Why to append elem to the body of the HTML? And why the code worked after removing it?


Solution

  • 1- Why the issue is happening

    That's a bug, that I couldn't reproduce on any browsers on macOS.

    , and what is the best solution?

    The best solution is to let know your browser's vendor that they have a bug, then you can try to add a delay before calling document.body.removeChild(elem);, so that the (async) download can actually begin before you mess with the element.
    One common practice is to wait a fair amount of time before doing this, which is also a good place to revoke the blob:// URL you did create, failing to do so will keep the Blob's data from being collected by the GC, causing a true memory leak once you remove your element and loose any track of the URL.

    So that would give something like

    elem.click();        
    setTimeout( () => {
      document.body.removeChild(elem);
      URL.revokeObjectURL(elem.href);
    }, 1e4); // 10s should be enough in most cases
    

    2- Why to append elem to the body of the HTML?

    Because it used to be required in some browsers (Firefox < 70).

    And why the code worked after removing it?

    That, only the ones that will try to fix your browser's bug will be able to tell you.