Need advice around options for handling a simple file download (.ics) in a Javascript app.
Assuming s.icsMsg is a well-formatted text/calendar string, the below works in Chrome:
var downloadLink = document.createElement("a");
downloadLink.href = 'data:text/calendar;charset=utf-8,' + s.icsMsg;
downloadLink.download = "Calendar.ics";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
File is downloaded, correctly named and opens into the mail client. In IE 9+ I get a data area size error.
Is there a way of achieving this in IE, purely on the client? I understand I can do it by setting the content-disposition in the http headers, but since the file is generate on the client-side, it's two extra hops to push it up, save it, then send it back with the correct headers (if that would even work).
Any advice would be great...
Found a solution. Works fine in IE10/11, anything earlier I'm just not showing the link that triggers this function. Figured the majority of users will be on mobile devices, so old IE won't be an issue.
Would use window.open() for non-IE browsers, but can't find how to set the file name. Not phased though, all is working.
if (!s.isIE) {
var downloadLink = document.createElement("a");
downloadLink.href = 'data:text/calendar;charset=utf-8,\r\n' + escape(s.icsMsg);
downloadLink.download = "Calendar.ics";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
else {
var blob = new Blob([s.icsMsg]);
window.navigator.msSaveOrOpenBlob(blob, 'Calendar.ics');
}
Related
I have an app that converts files. I'm sending a file, and the converted file is being returned in the form of a data URL. Had everything working great in Chrome, but IE (10/11/Edge) is a different story. Have tried several things to no prevail:
1) HTML5 download attribute is not supported in IE. I tried assigning the returned URL as an anchor tag href, but invoking .click() is not supported, and manually clicking on the link does nothing.
2) window.navigator.msSaveOrOpenBlob() and File Saver.js. The SaveAs dialog pops up, but the blob is empty and never downloads anything.
var file= new Blob([returnedFile], {type: "application/pdf"});
window.navigator.msSaveOrOpenBlob(file, 'doc.pdf');
FileSaver.saveAs(file, 'doc.pdf');
Any ideas or suggestions to try?
First, try to verify saveAs existance:
if (window.saveAs) {
window.saveAs(blob, name);
} else {
navigator.saveBlob(blob, name);
}
As for the Blob itself:
create <a>
update href:
a.href = window.URL.createObjectURL(new Blob(returnedFile, {type: "application/pdf"}));
fire click event
More or less the same functionality can be reviewed there: http://jsfiddle.net/VB59f/2/
Ended up getting the browser via navigator.userAgent.match and handling the save based on each browser accordingly:
var saveData = (data, fileName) => {
IE:
FileSaver.saveAs(blob, fileName + "." + extension);
Chrome:
var downloadLink = document.createElement("a");
document.body.appendChild(downloadLink);
downloadLink.style.display = "none";
downloadLink.href = data;
downloadLink.download = fileName;
downloadLink.click();
I just discovered today about the Blob() API, trying to download text into a file, from some input and span elements on my site. The problem is that the Blob(), no matter what type I give it, removes all the control codes, at least the essential ones like \n\r.
This is the code I am using to download data constructed as an ASCII file:
function saveTextAsFile2(){
var textToWrite = document.getElementById("inputTextToSave").value;
var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
var fileNameToSaveAs = document.getElementById("inputFileNameToSaveAs").value;
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();
}
I tried these types to no avail...
{type:'octet/stream'}
{type:'file'}
When the function is called the text is displayed in a textArea element as follows:
When downloaded, however, in the file it looks like this:
Line 1 - Fine line 2 - Line 3
If anyone could explain how this should be set up for the control codes to pass through the download, I would appreciate it greatly.
Regards,
DK
I discovered the answer, while testing things. It turns out that MS NotePad ignored the control codes as they come through the Blob(). All other editors recognize the control codes! Wackey stuff from MS! To avoid that problem, since I default to NotePad with the "*.txt" files, I will have to download with a different extension and fire it up with one of the other editors.
Thank you all who attempted to help by reading the question.
The good old Reagan slogan, Trust, but verify MS products still holds!
DK
Is it possible to overwrite a file each time it saves. I have a textarea in html and i'm using JavaScript to save the text to a file. It is currently saving as: test.txt, test(1).txt, test(2).txt. Is it possible to get it to save a test.txt every time it's downloaded.
The code i'm using to download is the following:
function saveTextAsFile()
{
var textToWrite = document.getElementById("inputTextToSave").value;
var textFileAsBlob = new Blob([textToWrite], {type:'plan/text'});
var fileNameToSaveAs = "test.txt";
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "My Hidden Link";
window.URL = window.URL || window.webkitURL;
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = destroyClickedElement;
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
downloadLink.click();
}
Thanks for your help.
No , a javascript script doesn't have access to the filesystem and therefore cant manipulate files, all it can do is suggest to the browser that a stream wants to be downloaded and also suggest a name for that stream. The browser is responsible for deciding what and how will be downloaded (you can add plugins and extensions to the browsers to enforce this particular behavior, but i do not think that this was what you needed)
EDIT:
On second note you could actually do that with a java applet. However i cannot help you with that, and in all sincerity, you should not (for one it wont work on chrome, also unless you have a really important reason to, it would be like killing a mosquito with a nuclear bomb, not to mention the chance of accidentally deleting a file from the user's side and a storm of alerts that would make your application look suspicious as it wont have any real reason to use java from they eyes of the user)
The following code works in both FireFox and Chrome, but not IE. Essentially, I have a JSON object which gets converted into an array and then to a csv format, when I click the button in FF or Chrome the file gets downloaded or the Save As window opens, but in IE a new tab opens up. In a perfect world IE would not exists, but in the real world we have to make it work, lol.
$("#csvbtn").click(function(e){
e.preventDefault();
var json_obj= JSON.parse(result);
var csv = JSON2CSV(json_obj);
window.open("data:text/csv;charset=utf-8," + escape(csv));
});
BTW, I am using IE 11 in windows 8 to test this, if that makes a difference.
Thanks all!
This is my solution in case someone else is looking for a solution. now it works with FF, Chrome , and IE
var csv = JSON2CSV(json_obj);
var blob = new Blob([csv],{type: "text/csv;charset=utf-8;"});
if (navigator.msSaveBlob) { // IE 10+
navigator.msSaveBlob(blob, "csvname.csv")
} else {
var link = document.createElement("a");
if (link.download !== undefined) { // feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", "csvname.csv");
link.style = "visibility:hidden";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
Now I just need to figure out if there is a way to have the save as screen pop up instead of automatically saving the file. If anybody knows the answer to that please share. For now my users will have to use this functionality.
Thanks all for all the great answers, you guys are awesome.
Internet Explorer does not permit data URIs as navigable content, for security purposes. To understand why, I would encourage you to read Henning Klevjer's short white-paper on the topic, Phishing by data URI. In summary, this has been demonstrated to open up avenues by which the end-user could be tricked into giving up sensitive information.
Also, from the data Protocol documentation on MSDN:
For security reasons, data URIs are restricted to downloaded resources. Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements.
To be honest, passing a data URI to window.open feels a bit hacky. Instead, you should use an API to handle the process (provided one exists). If you'd like to download a file to the user's machine in Internet Explorer, consider using navigator.msSaveBlob or navigator.msSaveOrOpenBlob.
As an example, consider the following:
if ( window.navigator.msSaveOrOpenBlob && window.Blob ) {
var blob = new Blob( [ "A,B\nC,D" ], { type: "text/csv" } );
navigator.msSaveOrOpenBlob( blob, "strings.csv" );
}
Is there any link for exporting the datas to notepad?
I have some fields like
Name,
Age, and
WorkingStatus
These are text and textarea...
I want to insert this datas to the notepad.Is there any demos or code available?
I don't know of any way to have the browser open notepad, but you can use HTML5 features to save a file as text, and then open it on your own inside notepad. Depending on the browser, you may need to trigger saving the file on the user side. Here's two references, which I'll summarize:
http://thiscouldbebetter.wordpress.com/2012/12/18/loading-editing-and-saving-a-text-file-in-html5-using-javascrip/
http://updates.html5rocks.com/2011/08/Saving-generated-files-on-the-client-side
Basically, you want to create and save a blob with your text. It should look something like this:
var arrayOfStuff = [];
arrayOfStuff.push("Name Age Working status");
arrayOfStuff.push("-----------------------------------------------");
arrayOfStuff.push(document.getElementById("name").value);
// etc
var blob = new Blob(arrayOfStuff, {type:'text/plain'});
// (the rest is copied directly from the wordpress link)
var downloadLink = document.createElement("a");
downloadLink.download = fileNameToSaveAs;
downloadLink.innerHTML = "Download File";
if (window.webkitURL != null)
{
// Chrome allows the link to be clicked programmatically.
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
downloadLink.click();
}
else
{
// Firefox requires the user to actually click the link.
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
document.body.appendChild(downloadLink);
}
If notepad isn't a big deal, you should also be able to open this blob in an iframe as .txt, and then right-click and saveAs, if you prefer.
Edit
Ok, this was actually new for me to play with, so some of my older information wasn't quite right. Here's the javascript from the working fiddle:
var arrayOfStuff = [];
arrayOfStuff.push(document.getElementById("name").value + "\n");
arrayOfStuff.push(document.getElementById("email").value);
arrayOfStuff.push("\n");
arrayOfStuff.push(document.getElementById("phone").value);
arrayOfStuff.push("\n");
arrayOfStuff.push(document.getElementById("comments").value);
arrayOfStuff.push("\n");
alert(arrayOfStuff);
var blob = new Blob(arrayOfStuff, {type:'text/plain'});
var link = document.getElementById("downloadLink");
link.download = "details.txt";
link.href = window.URL.createObjectURL(blob);
The fiddle is at http://jsfiddle.net/xHH46/2/
There are a few lessons learned:
If you're on firefox, it gives you the option to open the .txt immediately in Notepad. However, notepad isn't paying attention to the linefeeds, whether they're \n or \n\r, appended to the immediate string or added separately, so I'd recommend using Wordpad instead. Or, you can save the file.
More importantly, realize that the link you display is based on whatever value is in the text when you create the blob. If you don't have defaults, you'll get an empty file, because all the fields are empty. The wordpress solution fixes this (and discusses using it within the past week), but the fix is ugly. Basically, you'd have to click on a button, and the button would then make a link appear, and that link would give you the good file.
You won't be able to do this with purely javascript. You need to generate the file server side and send it to the client.