JavaScript blob filename without link

2018-12-31 14:08发布

问题:

How do you set the name of a blob file in JavaScript when force downloading it through window.location?

function newFile(data) {
    var json = JSON.stringify(data);
    var blob = new Blob([json], {type: \"octet/stream\"});
    var url  = window.URL.createObjectURL(blob);
    window.location.assign(url);
}

Running the above code downloads a file instantly without a page refresh that looks like:

bfefe410-8d9c-4883-86c5-d76c50a24a1d

I want to set the filename as my-download.json instead.

回答1:

The only way I\'m aware of is the trick used by FileSaver.js:

  1. Create a hidden <a> tag.
  2. Set its href attribute to the blob\'s URL.
  3. Set its download attribute to the filename.
  4. Click on the <a> tag.

Here is a simplified example (jsfiddle):

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

I wrote this example just to illustrate the idea, in production code use FileSaver.js instead.

Notes

  • Older browsers don\'t support the \"download\" attribute, since it\'s part of HTML5.
  • Some file formats are considered insecure by the browser and the download fails. Saving JSON files with txt extension works for me.


回答2:

I just wanted to expand on the accepted answer with support for Internet Explorer (most modern versions, anyways), and also tidying up the code using jQuery as well:

$(document).ready(function() {
    saveFile(\"Example.txt\", \"data:attachment/text\", \"Hello, world.\");
});

function saveFile (name, type, data) {
    if (data != null && navigator.msSaveBlob)
        return navigator.msSaveBlob(new Blob([data], { type: type }), name);
    var a = $(\"<a style=\'display: none;\'/>\");
    var url = window.URL.createObjectURL(new Blob([data], {type: type}));
    a.attr(\"href\", url);
    a.attr(\"download\", name);
    $(\"body\").append(a);
    a[0].click();
    window.URL.revokeObjectURL(url);
    a.remove();
}

Here is an example Fiddle. Godspeed.



回答3:

Same principle as the solutions above. But I had issues with Firefox 52.0 (32 bit) where large files (>40 MBytes) are truncated at random positions. Re-scheduling the call of revokeObjectUrl() fixes this issue.

function saveFile(blob, filename) {
  if (window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, filename);
  } else {
    const a = document.createElement(\'a\');
    document.body.appendChild(a);
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    setTimeout(() => {
      window.URL.revokeObjectURL(url);
      document.body.removeChild(a);
    }, 0)
  }
}


回答4:

saveFileOnUserDevice = function(file){ // content: blob, name: string
        if(navigator.msSaveBlob){ // For ie and Edge
            return navigator.msSaveBlob(file.content, file.name);
        }
        else{
            let link = document.createElement(\'a\');
            link.href = window.URL.createObjectURL(file.content);
            link.download = file.name;
            document.body.appendChild(link);
            link.dispatchEvent(new MouseEvent(\'click\', {bubbles: true, cancelable: true, view: window}));
            link.remove();
            window.URL.revokeObjectURL(link.href);
        }
    }


回答5:

Late, but as I had the same problem. I add my solution.

function newFile(data, fileName) {
    var json = JSON.stringify(data);
    //IE11 support
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        let blob = new Blob([csv], {type: \"text/csv\"});
        window.navigator.msSaveOrOpenBlob(blob, fileName);
    } else {// other browsers
        let file = new File([csv], fileName, {type: \"text/csv\"});
        let exportUrl = URL.createObjectURL(file);
        window.location.assign(exportUrl);
        URL.revokeObjectURL(exportUrl);
    }
}