Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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.

  • Create a hidden <a> tag.
  • Set its href attribute to the blob's URL.
  • Set its download attribute to the filename.
  • 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.
  • @AshBlue The "download" attribute needs HTML5. My code is just an example, you could also try the FileSaver.js demo page: eligrey.com/demos/FileSaver.js – kol Oct 13, 2013 at 8:57 Interestingly, if you repeatedly try to download a txt this way (by pressing the Run button on jsfiddle.net again and again), the download sometimes fails. – kol Oct 15, 2013 at 9:13 Just wanted to mention that this solution will not work for files with sizes greater than a particular threshold. e.g-> 2 MB for chrome. This size varies from browser to browser. – manojadams Sep 2, 2017 at 15:58 This does not work for me because I need to open the file in a new tab. I have to show a PDF in Chrome, but I need to show a user friendly name in the URL toolbar, and if the user wants to download through the download icon, I have to put the same user friendly name in the file. – Adrián Paredes Dec 11, 2017 at 14:42 Just to add, you don't need to actually mount the a tag to the body in order for this to work (tried just now in Chrome) – beyond-code Aug 12, 2019 at 10:37

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

    $(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.

    I used the accepted solution but it didn't work at firefox! I still don't know why. Your solution worked in firefox. Thanks. – elahehab Sep 30, 2019 at 7:57

    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)
    

    jsfiddle example

    I found that this setTimeout() hack fixes MS Edge, where the file would not download at all. However, only the call to revokeObjectURL() needs to be delayed. – Russell Phillips Dec 17, 2018 at 0:56 var json = JSON.stringify(data); //IE11 support if (window.navigator && window.navigator.msSaveOrOpenBlob) { let blob = new Blob([json], {type: "application/json"}); window.navigator.msSaveOrOpenBlob(blob, fileName); } else {// other browsers let file = new File([json], fileName, {type: "application/json"}); let exportUrl = URL.createObjectURL(file); window.location.assign(exportUrl); URL.revokeObjectURL(exportUrl);
    <button onclick="newFile({a:1}, 'file.json')">Export data to JSON</button>
    Thanks @ben. This is working fine. No dom elements, nothing like to trigger like click event. It just works awesome with proper extension. But the given file name is not considered, downloading "<object_url_id>.csv" instead of "<myfileName>.csv" – Ram Babu Jan 23, 2019 at 4:19 Calling revokeObjectURL after location.assign works fine in Firefox, but breaks the download on Chrome. – Fred Jan 25, 2019 at 15:49 As @RamBabuS says, this is not keeping fileName, but besides that works perfectly for me – Manu Artero Mar 5, 2020 at 16:41 The filename property works in firefox, but not in chrome... anyone a solution for chrome? – Gerros Sep 9, 2020 at 8:49 const a = document.createElement("a"); a.href = URL.createObjectURL( new Blob([JSON.stringify(data, null, 2)], { type: "application/json" a.setAttribute("download", "data.json"); document.body.appendChild(a); a.click(); document.body.removeChild(a);
    <button onclick="export2json()">Export data to json file</button>
    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);
    

    HTML:

    <button onclick="downloadUrl('https://i.imgur.com/AD3MbBi.jpg', 'cat.jpg')">Download</button>
    

    JavaScript:

    function downloadUrl(url, filename) {
      let xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.responseType = "blob";
      xhr.onload = function(e) {
        if (this.status == 200) {
          const blob = this.response;
          const a = document.createElement("a");
          document.body.appendChild(a);
          const blobUrl = window.URL.createObjectURL(blob);
          a.href = blobUrl;
          a.download = filename;
          a.click();
          setTimeout(() => {
            window.URL.revokeObjectURL(blobUrl);
            document.body.removeChild(a);
          }, 0);
      xhr.send();
    

    window.location.assign did not work for me. it downloads fine but downloads without an extension for a CSV file on Windows platform. The following worked for me.

        var blob = new Blob([csvString], { type: 'text/csv' });
        //window.location.assign(window.URL.createObjectURL(blob));
        var link = window.document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        // Construct filename dynamically and set to link.download
        link.download = link.href.split('/').pop() + '.' + extension; 
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    

    this is a good easy solution for it.

    function downloadBloob(blob,FileName) {
        var link = document.createElement("a"); // Or maybe get it from the current document
        link.href = blob;
        link.download = FileName;
        link.click();
                    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Ethan
                    Jun 4, 2022 at 13:47
                    This didn't work for me. You have to add "link.href = window.URL.createObjectURL(blob);" instead of "link.href = blob". Otherwise, it will give you an URL like this "localhost:3001/[object%20 Blob]" and the file will be empty and it will not work.
    – Eduard
                    Mar 24 at 10:34
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.