Thilo
Thilo

Reputation: 262814

Download textarea contents as a file using only Javascript (no server-side)

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?

Upvotes: 33

Views: 33189

Answers (9)

Lakshya Raj
Lakshya Raj

Reputation: 1775

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

Upvotes: 7

Cyrlop
Cyrlop

Reputation: 1984

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.

Upvotes: 10

NatureShade
NatureShade

Reputation: 2257

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>

Upvotes: 31

bbarker
bbarker

Reputation: 13108

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.

Upvotes: 4

superphonic
superphonic

Reputation: 8074

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.

Upvotes: 4

yacoob
yacoob

Reputation: 811

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

Upvotes: 7

Andrey Shchekin
Andrey Shchekin

Reputation: 21609

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

Upvotes: 1

olliej
olliej

Reputation: 36803

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.

Upvotes: 9

firem
firem

Reputation: 37

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

Upvotes: -2

Related Questions