29

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?

Nightfirecat
  • 11,114
  • 6
  • 33
  • 50
Thilo
  • 250,062
  • 96
  • 490
  • 643

10 Answers10

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>
Smart Manoj
  • 4,375
  • 4
  • 27
  • 51
NatureShade
  • 2,107
  • 1
  • 18
  • 27
  • Whilst this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – John Dvorak Oct 12 '13 at 09:20
  • Today it is not neccessary anymore to check for webkitURL. http://caniuse.com/#search=URL Seems also that Edge still doesnot support this feature – Wolfgang Blessen Jul 06 '17 at 07:03
  • 1
    "Error: destroyClickedElement is not defined" . copying code from the internet is not good for health. – crisc2000 Oct 07 '19 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.

Pedro404
  • 141
  • 4
Cyrlop
  • 1,814
  • 1
  • 15
  • 27
  • you are using an invalid content type; doesn't application/octet-stream have the same effect? – Julian Reschke Jul 05 '13 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 Oct 30 '15 at 16:31
  • @tamak, see my answer below based on this one. – bbarker May 15 '19 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.

olliej
  • 34,319
  • 9
  • 56
  • 55
7

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

yacoob
  • 801
  • 1
  • 11
  • 20
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.

superphonic
  • 7,818
  • 6
  • 29
  • 62
2

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.

bbarker
  • 9,715
  • 7
  • 34
  • 54
2

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

document.getElementById("dload").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;}
<!DOCTYPE html>
<html>
  <head>
    <title>Download File</title>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <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="dload">Download</button>
  </body>
</html>

This works in most browsers.

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

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

  1. data: URIs for having the data to download as a downloadable link. Click here for CanIUse browser compatability tables

  2. click() function to click the link. Click here for CanIUse browser compatability tables

  3. download attribute to signify a download. Click here for CanIUse browser compatability

So basically:

  • Does not work in IE

  • Does not work in Opera Mini

  • Does not work in 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 Constructing CanIUse compatibility tables

Blob URL CanIUse compatibility tables

Lakshya Raj
  • 1,094
  • 4
  • 20
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).

Andrey Shchekin
  • 20,337
  • 18
  • 91
  • 157
-1

Not working

document.getElementById("dload").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;}
<!DOCTYPE html>
<html>
  <head>
    <title>Download File</title>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <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="dload">Download</button>
  </body>
</html>
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 25 '21 at 09:54
-2

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

firem
  • 37
  • 1
  • This answer is objectively wrong given I've personally tested and gotten one of these answers working. – schizoid04 Jun 15 '21 at 15:53
  • Not sure how this ended up in the VLQ queue - it *is* an answer (just a possibly wrong one). [Wrong answers are not very low quality.](https://meta.stackoverflow.com/questions/345023/are-blatantly-wrong-answers-very-low-quality) – EJoshuaS - Stand with Ukraine Jun 15 '21 at 16:56