Reputation: 262814
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
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:
data:
URIs for storing the data as a link. data: URIs on CanIUse
click()
function to click the link. HTMLElement.click() on CanIUse
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.
Upvotes: 7
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
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
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
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
Reputation: 811
There were some javascript libraries that did this kind of thing, via small embedded SWF file. For example this one.
Upvotes: 7
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
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
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