32

I am being asked to make a "download" button that downloads the contents of a textarea on the same page as a file, with the browser's "Save As..." dialog showing up. Copy/paste would do the job just fine, but it is a "requirement".

Right now, I am just posting the contents of the textarea to the server, which echos them back with Content-disposition: attachment slapped on. Is there a way to do this with just client-side Javascript?

9 Answers 9

31

This may be what you are looking for: http://thiscouldbebetter.wordpress.com/2012/12/18/loading-editing-and-saving-a-text-file-in-html5-using-javascrip/

It uses the browser's download dialogue, but supports only FF and Chrome, and maybe more browsers now?


   function saveTextAsFile(textToWrite, fileNameToSaveAs)
    {
    	var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}); 
    	var downloadLink = document.createElement("a");
    	downloadLink.download = fileNameToSaveAs;
    	downloadLink.innerHTML = "Download File";
    	if (window.webkitURL != null)
    	{
    		// Chrome allows the link to be clicked
    		// without actually adding it to the DOM.
    		downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
    	}
    	else
    	{
    		// Firefox requires the link to be added to the DOM
    		// before it can be clicked.
    		downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
    		downloadLink.onclick = destroyClickedElement;
    		downloadLink.style.display = "none";
    		document.body.appendChild(downloadLink);
    	}
    
    	downloadLink.click();
    }
<textarea id=t>Hey</textarea><br>
<button onclick=saveTextAsFile(t.value,'download.txt')>Download</button>

3
  • Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. Commented Oct 12, 2013 at 9:20
  • Today it is not neccessary anymore to check for webkitURL. caniuse.com/#search=URL Seems also that Edge still doesnot support this feature Commented Jul 6, 2017 at 7:03
  • 1
    "Error: destroyClickedElement is not defined" . copying code from the internet is not good for health.
    – crisc2000
    Commented Oct 7, 2019 at 18:24
10

I found a simple solution here: https://codepen.io

My text area:<br />
<textarea rows='10' cols='80' id='myTextArea' ></textarea>

<br /><br />

Download button: <br />
<input value='download' type='button'
onclick='doDL(document.getElementById("myTextArea").value)' />


<script type='text/javascript'>
function doDL(s){
    function dataUrl(data) {return "data:x-application/text," + escape(data);}
    window.open(dataUrl(s));
}
</script>

Hope it will help.

3
  • you are using an invalid content type; doesn't application/octet-stream have the same effect? Commented Jul 5, 2013 at 11:42
  • @CyrLop -- awesome answer you posted here.... do you know if theres a way to hardcode a file name so the save dialoge opens with a filename the user can edit, but that is for instance, the current date -- yyyymmdd.txt ?
    – tamak
    Commented Oct 30, 2015 at 16:31
  • @tamak, see my answer below based on this one.
    – bbarker
    Commented May 15, 2019 at 15:59
9

You could try window.location = "data:application/octet-stream,"+text but that doesn't provide a mechanism through which you can suggest a name, and also IE has a very small cap on the maximum length of a data URI which could be a problem.

1
  • 2
    And it's not even possible with IE6.
    – Rakesh Pai
    Commented Mar 4, 2009 at 7:39
7

There were some javascript libraries that did this kind of thing, via small embedded SWF file. For example this one.

2
  • 1
    This is more of an answer to the question in my opinion. I mean, it helped me and thanks for that :) Commented Feb 28, 2012 at 23:14
  • Are there other libraries like this one?
    – Husman
    Commented May 13, 2014 at 10:10
5

You can use data: URIs and give it a file name, while still downloading the text. Try this:

document.getElementById("download").onclick = function(){
  var l = document.createElement("a");
  l.href = "data:text/plain;charset=UTF-8," + document.getElementById("dload-txt").value;
  l.setAttribute("download", document.getElementById("dload-fn").value);
  l.click();
}
textarea { width: 200px; height: 75px }
input { width: 200px }
<textarea placeholder="Enter text to download" id="dload-txt"></textarea><br/>
<input placeholder="Enter file name to download as" id="dload-fn"/><br/><br/>
<button id="download">Download</button>

This works in most browsers.

What it does is get the necessary data from the textarea and input, create a link that has an href to data:text/plain;UTF-8,<textarea data>, and set the download attribute with the name set by the <input> element. Then click the link, which will download the text.

The only not-all-browser-compatible things here are:

  1. data: URIs for storing the data as a link. data: URIs on CanIUse

  2. click() function to click the link. HTMLElement.click() on CanIUse

  3. download attribute to signify a download. download attribute on CanIUse

So basically:

  • Does not work in IE

  • Does not work in Opera Mini

  • Does not work in very early versions of Firefox, Chrome, Safari, Opera, and iOS Safari

Otherwise, this works in all major browsers, and doesn't need any Blob object.

Blob construction on CanIUse

Blob URLs on CanIUse

1
  • 1
    don't forget if you want to use special character like \n you have to encode the text l.href = "data:text/csv;charset=UTF-8," + encodeURIComponent(content); Commented Feb 8 at 10:59
4

Absolutely possible using this cross browser JavaScript implementation of the HTML5 saveAs function: https://github.com/koffsyrup/FileSaver.js

If all you want to do is save text then the above script works in all browsers(including all versions of IE), no SWF required.

4

Based on @Cyrlop's answer and https://stackoverflow.com/a/41948732/3096687, this gives a way to specify a filename:

            function doDownload(str) {
              function dataUrl(data) {
                return "data:x-application/xml;charset=utf-8," + escape(data);
              }
              var downloadLink = document.createElement("a");
              downloadLink.href = dataUrl(str);
              downloadLink.download = "foo.xml";

              document.body.appendChild(downloadLink);
              downloadLink.click();
              document.body.removeChild(downloadLink);
            }

@Superphonic's solution is likely nicer if you don't mind including more bytes in your JavaScript.

1
  • Know of any way to get it to prompt the user for a save as?
    – schizoid04
    Commented Jun 15, 2021 at 15:52
1

It might be possible by creating a frame, writing contents there, then calling document.execCommand('saveas', ...) in IE and something with nsIFilePicker in Mozilla, but I believe that would require some extraordinary privileges (like being part of the browser itself).

2
  • Possible indeed and requires no special privilege.. see here: jsfiddle.net/YhdSC/1 (IE only though :/) Commented Dec 16, 2010 at 9:53
  • Yes, the privilege part was more about Firefox. Commented Dec 16, 2010 at 14:58
-2

Short answer: it's not posible. You have to POST it to server, and response from server can be "Content-disposition: attachment".

2

Not the answer you're looking for? Browse other questions tagged or ask your own question.