I'm sure this is noobish but I am not JS guy. I'm just helping someone out with a simple form.
I have a text area where some custom XML data is written based on input from the user. It displays in the readonly text area so they can see what they are creating but I also have a button that will download it to the correct file name so they can upload it to another system we support.
I used the code here and modified for my own situation.
Works flawlessly in Chrome but nothing happens at all in Firefox (or IE but I don't particularly care a great deal about that one). Nothing at all appears in the console/log in FF.
Here's the js
function saveTextAsFile()
{
var textToWrite = document.getElementById("XMLTextArea").value;
var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
var fileNameToSaveAs = "MyFile.xml";
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.URL != null)
{
// Chrome allows the link to be clicked
// without actually adding it to the DOM.
downloadLink.href = window.URL.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();
}
function destroyClickedElement(event)
{
document.body.removeChild(event.target);
}
And relevant HTML
<textarea readonly id= 'XMLTextArea' cols='100' rows='40' > BLAH </textarea>
<button onclick="saveTextAsFile()">Save XML File</button>
Related
I've a problem with my website. I want when an user add an image from
this input :
`input type="file" class="form-control-file" id="Image" name="Image">`
I want to automatically download this image. I would prefer to download from front end. I try in JavaScript but not working.... Does anyone have an idea please ?
I despair.
Anatole
Edit : I want to download the image in my website folder ^^
you can add onchange listener that track input change
user input
<input oninput="onclickhandler(this)"></input>
script
<script>
function download(filename, url) {
var element = document.createElement('a');
element.setAttribute('href', url);
element.setAttribute('download', filename);
document.body.appendChild(element);
element.click();
//remove the hidden link
//document.body.removeChild(element);
}
function onclickhandler(e) {
var name = e.files[0].name;
var file = e.files[0];
var blob = new Blob([file]);
var url = URL.createObjectURL(blob);
download(name,url);
}
</script>
I searched a lot but couldn't find a solution I thank anyone who can help me.
I want to download files on button click but based on values in the text of buttons.
I have three buttons in my HTML like this
<input type="button" onclick="myFunction(this, name1.mp3)" value="button1.mp3">
<input type="button" onclick="myFunction(this, name2.mp3)" value="button2.mp3">
<input type="button" onclick="myFunction(this, name3.mp3)" value="button3.mp3">
my JavaScript is
function myFunction(elmnt, name) {
var url = "http://mysite*com/" + elmnt.value;
var downloadFileWithThisName = name;
---my download code---
}
How can I download my url with the name I passed to function?
what should I write for ---my download code--- part?
Thank you in advance.
function myFunction(elmnt, name) {
var url = "http://mysite*com/" + elmnt.value;
const a = document.createElement('a');
a.href = url;
a.download = name; // here you can specify your filename
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}
What you could do is to dynamically create an A element, add the 'download' attribute, set the Href and click it, all in code. Then remove it from the DOM.
The best answer judging for your code is shown here: https://stackoverflow.com/a/42696866/1891140
var file_path = 'host/path/file.ext';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
But you also can do it by using a simple JQUERY:
$("<a href='"+url+"' download class='hidden-a'></a>").appendTo("body");
$(".hidden-a")[0].click();
Could someone help me save the contents of a HTML5 textArea to file, preferably using JavaScript?
<textarea id="textArea">
Notes here...
</textarea>
<button type="button" value="save"> Save</button>
That should do it.
function saveTextAsFile() {
var textToWrite = document.getElementById('textArea').innerHTML;
var textFileAsBlob = new Blob([ textToWrite ], { type: 'text/plain' });
var fileNameToSaveAs = "file.txt"; //filename.extension
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();
}
var button = document.getElementById('save');
button.addEventListener('click', saveTextAsFile);
function destroyClickedElement(event) {
// remove the link from the DOM
document.body.removeChild(event.target);
}
#textArea {
display: block;
width: 100%;
}
<textarea id="textArea" rows="3">
Notes here...
</textarea>
<button type="button" value="save" id="save">Save</button>
JSFiddle
A simplified version of the code in the answers:
function download(){
var text = document.getElementById("my-textarea").value;
text = text.replace(/\n/g, "\r\n"); // To retain the Line breaks.
var blob = new Blob([text], { type: "text/plain"});
var anchor = document.createElement("a");
anchor.download = "my-filename.txt";
anchor.href = window.URL.createObjectURL(blob);
anchor.target ="_blank";
anchor.style.display = "none"; // just to be safe!
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
}
and the html:
<textarea id="my-textarea">
Notes here...
</textarea>
<button type="button" onclick="download()">Save</button>
I tested engincancan's answer, and it was almost there, but not quite. First of all, the file format for "ecc.plist" was not recognizable anywhere. Second of all, in order for the code to work on the desktop in Safari, Chrome, and Firefox, you have to use an existing anchor tag and not create one (document.createElement('a')). The destroyClickedElement approach only works in Chrome, because it is so forgiving and lenient. And, in order for the download to work in Firefox, you have to have document.body.appendChild(downloadLink.download);
I also had wanted to save my local storage text to a file for download and the code works on desktop for Safari, Chrome and Firefox on Mac. However, I think it is impossible in iOS to save the Blob() anywhere with Chrome or Firefox. It does work, interestingly enough in Safari. For example, I can save the text file to my Wunderlist app. Here is the link my repo on Github: The Cat Whisperer on Github gh-pages
Here is the JavaScript code:
const fileDownloadButton = document.getElementById('save');
function localStorageToFile() {
const csv = JSON.stringify(localStorage['autosave']);
const csvAsBlob = new Blob([csv], {type: 'text/plain'});
const fileNameToSaveAs = 'local-storage.txt';
const downloadLink = document.getElementById('save');
downloadLink.download = fileNameToSaveAs;
if (window.URL !== null) {
// Chrome allows the link to be clicked without actually adding it to the DOM
downloadLink.href = window.URL.createObjectURL(csvAsBlob);
downloadLink.target = `_blank`;
} else {
downloadLink.href = window.URL.createObjectURL(csvAsBlob);
downloadLink.target = `_blank`;
downloadLink.style.display = 'none';
// add .download so works in Firefox desktop.
document.body.appendChild(downloadLink.download);
}
downloadLink.click();
}
// file download button event listener
fileDownloadButton.addEventListener('click', localStorageToFile);
<textarea id = "textArea">
Notes here...
</textarea>
<button onclick="savetextarea()" type="button">Save</button>
<script>
function savetextarea(){
var txt = document.getElementById("textArea").value;
document.getElementById("saveinput").value = txt;
document.forms["aForm"].submit();
}
</script>
<form action="savecontent" name="aForm">
<input id="saveinput" type="hidden" name="filecontent" value="">
</form>
If we were on a nodeJS server, we could write a header, set a mime type, and send it:
res.header("Content-Disposition", "attachment;filename="+name+".csv");
res.type("text/csv");
res.send(200, csvString);
and because of the headers, the browser will create a download for the named csv file.
When useful data is generated in a browser, one solution to getting it in a CSV file is to use ajax, upload it to the server, (perhaps optionally save it there) and get the server to send it back with these headers to become a csv download back at the browser.
However, I would like a 100% browser solution that does not involve ping-pong with the server.
So it occurred to me that one could open a new window and try to set the header with a META tag equivalent.
But this doesn't work for me in recent Chrome.
I do get a new window, and it contains the csvString, but does not act as a download.
I guess I expected to get either a download in a bottom tab or a blank new window with a download in a bottom tab.
I'm wondering if the meta tags are correct or if other tags are also needed.
Is there a way to make this work without punting it to the server?
JsFiddle for Creating a CSV in the Browser (not working - outputs window but no download)
var A = [['n','sqrt(n)']]; // initialize array of rows with header row as 1st item
for(var j=1;j<10;++j){ A.push([j, Math.sqrt(j)]) }
var csvRows = [];
for(var i=0,l=A.length; i<l; ++i){
csvRows.push(A[i].join(',')); // unquoted CSV row
}
var csvString = csvRows.join("\n");
console.log(csvString);
var csvWin = window.open("","","");
csvWin.document.write('<meta name="content-type" content="text/csv">');
csvWin.document.write('<meta name="content-disposition" content="attachment; filename=data.csv"> ');
csvWin.document.write(csvString);
There's always the HTML5 download attribute :
This attribute, if present, indicates that the author intends the
hyperlink to be used for downloading a resource so that when the user
clicks on the link they will be prompted to save it as a local file.
If the attribute has a value, the value will be used as the pre-filled
file name in the Save prompt that opens when the user clicks on the
link.
var A = [['n','sqrt(n)']];
for(var j=1; j<10; ++j){
A.push([j, Math.sqrt(j)]);
}
var csvRows = [];
for(var i=0, l=A.length; i<l; ++i){
csvRows.push(A[i].join(','));
}
var csvString = csvRows.join("%0A");
var a = document.createElement('a');
a.href = 'data:attachment/csv,' + encodeURIComponent(csvString);
a.target = '_blank';
a.download = 'myFile.csv';
document.body.appendChild(a);
a.click();
FIDDLE
Tested in Chrome and Firefox, works fine in the newest versions (as of July 2013).
Works in Opera as well, but does not set the filename (as of July 2013).
Does not seem to work in IE9 (big suprise) (as of July 2013).
An overview over what browsers support the download attribute can be found Here
For non-supporting browsers, one has to set the appropriate headers on the serverside.
Apparently there is a hack for IE10 and IE11, which doesn't support the download attribute (Edge does however).
var A = [['n','sqrt(n)']];
for(var j=1; j<10; ++j){
A.push([j, Math.sqrt(j)]);
}
var csvRows = [];
for(var i=0, l=A.length; i<l; ++i){
csvRows.push(A[i].join(','));
}
var csvString = csvRows.join("%0A");
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([csvString]);
window.navigator.msSaveOrOpenBlob(blob, 'myFile.csv');
} else {
var a = document.createElement('a');
a.href = 'data:attachment/csv,' + encodeURIComponent(csvString);
a.target = '_blank';
a.download = 'myFile.csv';
document.body.appendChild(a);
a.click();
}
#adeneo answer works for Firefox and chrome... For IE the below can be used.
if (window.navigator.msSaveOrOpenBlob) {
var blob = new Blob([decodeURIComponent(encodeURI(result.data))], {
type: "text/csv;charset=utf-8;"
});
navigator.msSaveBlob(blob, 'FileName.csv');
}
See adeneo's answer, but don't forget encodeURIComponent!
a.href = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csvString);
Also, I needed to do "\r\n" not just "\n" for the row delimiter.
var csvString = csvRows.join("\r\n");
Revised fiddle: http://jsfiddle.net/7Q3c6/
Once I packed JS code doing that to a tiny library:
https://github.com/AlexLibs/client-side-csv-generator
The Code, Documentation and Demo/Playground are provided on Github.
Enjoy :)
Pull requests are welcome.
We can easily create and export/download the excel file with any separator (in this answer I am using the comma separator) using javascript. I am not using any external package for creating the excel file.
var Head = [[
'Heading 1',
'Heading 2',
'Heading 3',
'Heading 4'
]];
var row = [
{key1:1,key2:2, key3:3, key4:4},
{key1:2,key2:5, key3:6, key4:7},
{key1:3,key2:2, key3:3, key4:4},
{key1:4,key2:2, key3:3, key4:4},
{key1:5,key2:2, key3:3, key4:4}
];
for (var item = 0; item < row.length; ++item) {
Head.push([
row[item].key1,
row[item].key2,
row[item].key3,
row[item].key4
]);
}
var csvRows = [];
for (var cell = 0; cell < Head.length; ++cell) {
csvRows.push(Head[cell].join(','));
}
var csvString = csvRows.join("\n");
let csvFile = new Blob([csvString], { type: "text/csv" });
let downloadLink = document.createElement("a");
downloadLink.download = 'MYCSVFILE.csv';
downloadLink.href = window.URL.createObjectURL(csvFile);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
See adeneo's answer, but to make this work in Excel in all countries you should add "SEP=," to the first line of the file. This will set the standard separator in Excel and will not show up in the actual document
var csvString = "SEP=, \n" + csvRows.join("\r\n");
I have converted the source content from the <img> html tag to a base64String using JavaScript. The image was displayed clearly. Now I want to save that image to user's disk using javascript.
<html>
<head>
<script>
function saveImageAs () {
var imgOrURL;
embedImage.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA" +
"AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO" +
"9TXL0Y4OHwAAAABJRU5ErkJggg==";
imgOrURL = embedImage;
if (typeof imgOrURL == 'object')
imgOrURL = embedImage.src;
window.win = open(imgOrURL);
setTimeout('win.document.execCommand("SaveAs")', 0);
}
</script>
</head>
<body>
<a href="#" ONCLICK="saveImageAs(); return false" >save image</a>
<img id="embedImage" alt="Red dot">
</body>
</html>
This code worked well when I set the image path as source for <img> html tag. However, when I pass the source as base64String does not work.
How to achieve what I want?
HTML5 download attribute
Just to allow user to download the image or other file you may use the HTML5 download attribute.
Static file download
<a href="/images/image-name.jpg" download>
<!-- OR -->
<a href="/images/image-name.jpg" download="new-image-name.jpg">
Dynamic file download
In cases requesting image dynamically it is possible to emulate such download.
If your image is already loaded and you have the base64 source then:
function saveBase64AsFile(base64, fileName) {
var link = document.createElement("a");
document.body.appendChild(link); // for Firefox
link.setAttribute("href", base64);
link.setAttribute("download", fileName);
link.click();
}
Otherwise if image file is downloaded as Blob you can use FileReader to convert it to Base64:
function saveBlobAsFile(blob, fileName) {
var reader = new FileReader();
reader.onloadend = function () {
var base64 = reader.result ;
var link = document.createElement("a");
document.body.appendChild(link); // for Firefox
link.setAttribute("href", base64);
link.setAttribute("download", fileName);
link.click();
};
reader.readAsDataURL(blob);
}
Firefox
The anchor tag you are creating also needs to be added to the DOM in Firefox, in order to be recognized for click events (Link).
IE is not supported: Caniuse link
In JavaScript you cannot have the direct access to the filesystem.
However, you can make browser to pop up a dialog window allowing the user to pick the save location. In order to do this, use the replace method with your Base64String and replace "image/png" with "image/octet-stream":
"data:image/png;base64,iVBORw0KG...".replace("image/png", "image/octet-stream");
Also, W3C-compliant browsers provide 2 methods to work with base64-encoded and binary data:
atob()
btoa()
Probably, you will find them useful in a way...
Here is a refactored version of what I understand you need:
window.addEventListener('DOMContentLoaded', () => {
const img = document.getElementById('embedImage');
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA' +
'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO' +
'9TXL0Y4OHwAAAABJRU5ErkJggg==';
img.addEventListener('load', () => button.removeAttribute('disabled'));
const button = document.getElementById('saveImage');
button.addEventListener('click', () => {
window.location.href = img.src.replace('image/png', 'image/octet-stream');
});
});
<!DOCTYPE html>
<html>
<body>
<img id="embedImage" alt="Red dot" />
<button id="saveImage" disabled="disabled">save image</button>
</body>
</html>
This Works
function saveBase64AsFile(base64, fileName) {
var link = document.createElement("a");
document.body.appendChild(link);
link.setAttribute("type", "hidden");
link.href = "data:text/plain;base64," + base64;
link.download = fileName;
link.click();
document.body.removeChild(link);
}
Based on the answer above but with some changes
Check out https://github.com/eligrey/FileSaver.js/ which wraps the HTML5 method and provides workarounds for e.g. IE10.