How to get a web browser to download a file that is stored in a JavaScript String?

13,297

In some newer browsers you can use the new HTML5 download attribute on the a tag to achieve this:

var a = document.createElement('a');
a.download = "filename.txt";
a.href = "data:application/octet-stream;base64," + Base64.encode(myFileContents);
a.click();

For a future solution you could look into the HTML5 FileSystem API, but this API is not currently supported in most of the major browsers. It might not be of much use to you except for that it might provide you with another way to store the files locally if you would be OK with that. But it doesn't store the files on the users locally accessible file system, you would have to develop your own browser based interface for your users to interact with the files. Downloading the files from the HTML5 file system to the users local file system would in any case again be done using the new download attribute on an a tag, which would then refer to a location in the HTML5 file system instead of referring to an online location.

To do this with an iframe element you would have to somehow set the Content-Disposition request header on the iframe to inline; filename="filename.txt" using client side JavaScript, I don't think it is possible to do this, most likely because of security issues. If you really don't have any other option, you could kill the download speed performance by sending the string to the server using AJAX and then downloading it from there again with the right request headers set.

Share:
13,297
Sean N.
Author by

Sean N.

Updated on June 17, 2022

Comments

  • Sean N.
    Sean N. almost 2 years

    I've been able to write JavaScript to cause the browser to download a file from a remote server using code like this:

    var iframe = document.createElement("iframe");
    iframe.style.display = "none";
    iframe.src = "filename.zip"
    document.body.appendChild(iframe);
    

    Which works great. However, now I have a different situation where the contents of the file are stored in a string in my JavaScript on the browser side and I need to trigger a download of that file. I've tried replacing the third line above with this, where 'myFileContents' is the string containing the actual bytes of the file:

    iframe.src = "data:application/octet-stream;base64," + Base64.encode(myFileContents);
    

    This gets the file downloaded, but the file name is lost. In Chrome the file name is just 'download'. Also I've read that there are limitations to the file size allowed in some browser versions.

    Is there a way to achieve this? Using JQuery would be OK. The solution needs to support any file type - zip, pdf, csv, png, jpg, xls, etc...

  • Sean N.
    Sean N. almost 11 years
    Thanks. I did find another post where someone mentioned the trick of posting the file contents and filename to the web server, and then having it return the full response with Content-disposition header. An example implementation is here: code.google.com/p/download-data-uri. I was trying to avoid that method because of performance issues by the redundant transmission. I'll try out the 'a.download' trick and look into what browsers support it. Thanks.
  • Sean N.
    Sean N. almost 11 years
    Your solution works very well in Chrome, but does not currently work in any other browsers. I'm accepting this answer until a better suggestion is made. I was thinking there might still be a way to use the iframe trick with some sort of fake ajax post and fake response, but I wouldn't know how to do this.
  • Sean N.
    Sean N. almost 11 years
    Instead of a.click() you can use var clickEvent = document.createEvent("MouseEvent"); clickEvent.initEvent("click", true, true); a.dispatchEvent(clickEvent); to make it work in Firefox & Chrome
  • Paulius Dragunas
    Paulius Dragunas about 6 years
    this now doesn't work with Chrome 65 developers.google.com/web/updates/2018/02/…