10

Trying to initiate a browser download in Javascript, but the data I want to be downloaded is in a string, not a file. I know if it were a file, the following would do it:

window.location.href = '/filepath/file.csv';

How can I get this same effect, only with a string (with csv data), not a file that already exists on the server?

Joe Bergevin
  • 3,158
  • 5
  • 26
  • 34

2 Answers2

19

using my handy downloader:

<script src="http://danml.com/js/download.js"></script>
<script>download("hello world", "hello.txt", "text/plain")</script>

you can do it without a library as well, though my "lib" isn't very big and supports older FF+CH and IE10:

<a id=dl download="file.txt">Download</a>
<script>
content=prompt("enter contents");
dl.href="data:text/plain,"+encodeURIComponent(content);
dl.click();
</script>

EDIT: the linked script now supports window.URL.createObjectURL() for downloading files that were too big using dataURLs. I don't know the new limit, but 10mb works just file, whereas ~2mb is a limit for many dataURL ( window.open/A[download] - based ) solutions3

dandavis
  • 16,370
  • 5
  • 40
  • 36
  • Amazing!! I don't only like your implementation relies on timeout but it's really nice to know it's possible to do. – zerkms Feb 19 '14 at 22:08
  • the timeout is to allow the DOM modification to "sink in" before the script thread tries to hit it. It's needed for reliability unless you adjust the script to recycle the temp anchor tag... – dandavis Feb 19 '14 at 22:14
  • Yep, I understand that. It's probably something irrational - when I see a code that relies on timeout rather than on events - I'm subconsciously starting thinking there is something wrong with it. – zerkms Feb 19 '14 at 22:18
  • 2
    well if the dom modifications events ever got their $#1t together, i would use those... – dandavis Feb 19 '14 at 22:20
1

Below is a function I have writen in the past to handle such behavior (it may require some tweaking):

var downloadFile = function (filename, dataValue) {
    window.URL = window.webkitURL || window.URL;
    window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;

    var prevLink = output.querySelector('a');
    if (prevLink) {
        window.URL.revokeObjectURL(prevLink.href);
        output.innerHTML = '';
    }

    var a = document.createElement('a');
    a.download = '" + filename + @".csv';

    if (BlobBuilder == undefined) {
        var bb = new Blob([dataValue], { 'type': MIME_TYPE });
        a.href = window.URL.createObjectURL(bb);
    }
    else {
        var bb = new BlobBuilder();
        bb.append(dataValue);
        a.href = window.URL.createObjectURL(bb.getBlob(MIME_TYPE));
    }

    a.textContent = 'Download ready';

    a.dataset.downloadurl = [MIME_TYPE, a.download, a.href].join(':');
    a.draggable = true; // Don't really need, but good practice.
    a.classList.add('dragout');

    output.appendChild(a);

    a.onclick = function (e) {
        if ('disabled' in this.dataset) {
            return false;
        }
    };
};
malkassem
  • 1,937
  • 1
  • 20
  • 39