Here What I am trying to do but not able to achieve the result.The data is getting downloaded without the '.csv' extension.
function get_modal1(data) {
$("#popupcontent").html(data);
var t = document.getElementById('tablename').innerText;
$('title').html(t);
$('#example').DataTable({
dom: 'lBfrtip',
buttons: [
'csv',
]
} );
this is how the data table is get exported without the extension .csv
I am not able to export the data as .csv. What I am doing wrong here?
The data is getting downloaded and when I open it with notepad it is comma separated.What could be the problem here?
[1]:
It's a bit of a rewrite but this is what I'd do, assuming your function is what will format the data and cause the file download:
function get_modal1(_data) {
// create a blob in memory of type text/csv
var _blob = new Blob([_data], {type: 'text/csv'});
var _file = "my_data.csv";
// create an anchor in memory for the file
var anc = document.createElement('a');
anc.style = "display: none";
// populate the url with the blob
var _f_url = window.URL.createObjectURL(blob);
anc.href = _f_url;
anc.download = _file;
// In case you have to support IE 11, IE 11 cannot handle dynamic click of an anchor to initiate save, so use msSaveBlob instead.
// in any case, fire the anchor link just created... user should get the file at this point.
if ( window.navigator.msSaveBlob ) {
window.navigator.msSaveBlob(blob, _file);
} else {
anc.dispatchEvent(new MouseEvent('click'));
}
// clear url out of memory to be safe.
window.URL.revokeObjectURL(_f_url);
});
Related
I want to Write Data to existing file using JavaScript.
I don't want to print it on console.
I want to Actually Write data to abc.txt.
I read many answered question but every where they are printing on console.
at some place they have given code but its not working.
So please can any one help me How to actually write data to File.
I referred the code but its not working:
its giving error:
Uncaught TypeError: Illegal constructor
on chrome and
SecurityError: The operation is insecure.
on Mozilla
var f = "sometextfile.txt";
writeTextFile(f, "Spoon")
writeTextFile(f, "Cheese monkey")
writeTextFile(f, "Onion")
function writeTextFile(afilename, output)
{
var txtFile =new File(afilename);
txtFile.writeln(output);
txtFile.close();
}
So can we actually write data to file using only Javascript or NOT?
You can create files in browser using Blob and URL.createObjectURL. All recent browsers support this.
You can not directly save the file you create, since that would cause massive security problems, but you can provide it as a download link for the user. You can suggest a file name via the download attribute of the link, in browsers that support the download attribute. As with any other download, the user downloading the file will have the final say on the file name though.
var textFile = null,
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
// returns a URL you can use as a href
return textFile;
};
Here's an example that uses this technique to save arbitrary text from a textarea.
If you want to immediately initiate the download instead of requiring the user to click on a link, you can use mouse events to simulate a mouse click on the link as Lifecube's answer did. I've created an updated example that uses this technique.
var create = document.getElementById('create'),
textbox = document.getElementById('textbox');
create.addEventListener('click', function () {
var link = document.createElement('a');
link.setAttribute('download', 'info.txt');
link.href = makeTextFile(textbox.value);
document.body.appendChild(link);
// wait for the link to be added to the document
window.requestAnimationFrame(function () {
var event = new MouseEvent('click');
link.dispatchEvent(event);
document.body.removeChild(link);
});
}, false);
Some suggestions for this -
If you are trying to write a file on client machine, You can't do this in any cross-browser way. IE does have methods to enable "trusted" applications to use ActiveX objects to read/write file.
If you are trying to save it on your server then simply pass on the text data to your server and execute the file writing code using some server side language.
To store some information on the client side that is considerably small, you can go for cookies.
Using the HTML5 API for Local Storage.
If you are talking about browser javascript, you can not write data directly to local file for security reason. HTML 5 new API can only allow you to read files.
But if you want to write data, and enable user to download as a file to local. the following code works:
function download(strData, strFileName, strMimeType) {
var D = document,
A = arguments,
a = D.createElement("a"),
d = A[0],
n = A[1],
t = A[2] || "text/plain";
//build download link:
a.href = "data:" + strMimeType + "charset=utf-8," + escape(strData);
if (window.MSBlobBuilder) { // IE10
var bb = new MSBlobBuilder();
bb.append(strData);
return navigator.msSaveBlob(bb, strFileName);
} /* end if(window.MSBlobBuilder) */
if ('download' in a) { //FF20, CH19
a.setAttribute("download", n);
a.innerHTML = "downloading...";
D.body.appendChild(a);
setTimeout(function() {
var e = D.createEvent("MouseEvents");
e.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.dispatchEvent(e);
D.body.removeChild(a);
}, 66);
return true;
}; /* end if('download' in a) */
//do iframe dataURL download: (older W3)
var f = D.createElement("iframe");
D.body.appendChild(f);
f.src = "data:" + (A[2] ? A[2] : "application/octet-stream") + (window.btoa ? ";base64" : "") + "," + (window.btoa ? window.btoa : escape)(strData);
setTimeout(function() {
D.body.removeChild(f);
}, 333);
return true;
}
to use it:
download('the content of the file', 'filename.txt', 'text/plain');
Try
let a = document.createElement('a');
a.href = "data:application/octet-stream,"+encodeURIComponent("My DATA");
a.download = 'abc.txt';
a.click();
If you want to download binary data look here
Update
2020.06.14 I upgrade Chrome to 83.0 and above SO snippet stop works (reason: sandbox security restrictions) - but JSFiddle version works - here
Above answer is useful but, I found code which helps you to download text file directly on button click.
In this code you can also change filename as you wish. It's pure javascript function with HTML5.
Works for me!
function saveTextAsFile()
{
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.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();
}
const data = {name: 'Ronn', age: 27}; //sample json
const a = document.createElement('a');
const blob = new Blob([JSON.stringify(data)]);
a.href = URL.createObjectURL(blob);
a.download = 'sample-profile'; //filename to download
a.click();
Check Blob documentation here - Blob MDN to provide extra parameters for file type. By default it will make .txt file
In the case it is not possibile to use the new Blob solution, that is for sure the best solution in modern browser, it is still possible to use this simpler approach, that has a limit in the file size by the way:
function download() {
var fileContents=JSON.stringify(jsonObject, null, 2);
var fileName= "data.json";
var pp = document.createElement('a');
pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
pp.setAttribute('download', fileName);
pp.click();
}
setTimeout(function() {download()}, 500);
$('#download').on("click", function() {
function download() {
var jsonObject = {
"name": "John",
"age": 31,
"city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";
var pp = document.createElement('a');
pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
pp.setAttribute('download', fileName);
pp.click();
}
setTimeout(function() {
download()
}, 500);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="download">Download me</button>
Use the code by the user #useless-code above (https://stackoverflow.com/a/21016088/327386) to generate the file.
If you want to download the file automatically, pass the textFile that was just generated to this function:
var downloadFile = function downloadURL(url) {
var hiddenIFrameID = 'hiddenDownloader',
iframe = document.getElementById(hiddenIFrameID);
if (iframe === null) {
iframe = document.createElement('iframe');
iframe.id = hiddenIFrameID;
iframe.style.display = 'none';
document.body.appendChild(iframe);
}
iframe.src = url;
}
I found good answers here, but also found a simpler way.
The button to create the blob and the download link can be combined in one link, as the link element can have an onclick attribute. (The reverse seems not possible, adding a href to a button does not work.)
You can style the link as a button using bootstrap, which is still pure javascript, except for styling.
Combining the button and the download link also reduces code, as fewer of those ugly getElementById calls are needed.
This example needs only one button click to create the text-blob and download it:
<a id="a_btn_writetofile" download="info.txt" href="#" class="btn btn-primary"
onclick="exportFile('This is some dummy data.\nAnd some more dummy data.\n', 'a_btn_writetofile')"
>
Write To File
</a>
<script>
// URL pointing to the Blob with the file contents
var objUrl = null;
// create the blob with file content, and attach the URL to the downloadlink;
// NB: link must have the download attribute
// this method can go to your library
function exportFile(fileContent, downloadLinkId) {
// revoke the old object URL to avoid memory leaks.
if (objUrl !== null) {
window.URL.revokeObjectURL(objUrl);
}
// create the object that contains the file data and that can be referred to with a URL
var data = new Blob([fileContent], { type: 'text/plain' });
objUrl = window.URL.createObjectURL(data);
// attach the object to the download link (styled as button)
var downloadLinkButton = document.getElementById(downloadLinkId);
downloadLinkButton.href = objUrl;
};
</script>
Here is a single-page local-file version for use when you need the extra processing functionality of a scripting language.
Save the code below to a text file
Change the file extension from '.txt' to '.html'
Right-click > Open With... > notepad
Program word processing as needed, then save
Double-click html file to open in default browser
Result will be previewed in the black box, click download to get the resulting text file
Code:
<!DOCTYPE HTML>
<HTML>
<HEAD>
</HEAD>
<BODY>
<SCRIPT>
// do text manipulation here
let string1 = 'test\r\n';
let string2 = 'export.';
// assemble final string
const finalText = string1 + string2;
// convert to blob
const data = new Blob([finalText], {type: 'text/plain'});
// create file link
const link = document.createElement('a');
link.innerHTML = 'download';
link.setAttribute('download', 'data.txt');
link.href = window.URL.createObjectURL(data);
document.body.appendChild(link);
// preview the output in a paragraph
const htmlBreak = string => {
return string.replace(/(?:\r\n|\r|\n)/g, '<br>');
}
const preview = document.createElement('p');
preview.innerHTML = htmlBreak(finalText);
preview.style.border = "1px solid black";
document.body.appendChild(preview);
</SCRIPT>
</BODY>
</HTML>
I have an Ionic application which downloads a file from a Web API. The content of the file can be found in the _body property of the HTTP response.
What I'm trying to do is convert this text into an arrayBuffer so I can save the content into a file.
However, the issue that I'm having is that any file (PDF files in my instance) that have images and/or large in size either don't show up at all or show up as correputed files.
At first I thought this was an issue relating Ionic. So to make sure I tried to simulate this issue and I was able to reproduce it.
Is this snippet you can select a PDF file, then download it. You would find that the downloaded file is corrupted and exactly how my Ionic app displays them.
HTML:
<input type="file" id="file_input" class="foo" />
<div id="output_field" class="foo"></div>
JS:
$(document).ready(function(){
$('#file_input').on('change', function(e){
readFile(this.files[0], function(e) {
//manipulate with result...
$('#output_field').text(e.target.result);
try {
var file = new Blob([e.target.result], { type: 'application/pdf;base64' });
var fileURL = window.URL.createObjectURL(file);
var seconds = new Date().getTime() / 1000;
var fileName = "cert" + parseInt(seconds) + ".pdf";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = fileURL;
a.download = fileName;
a.click();
}
catch (err){
$('#output_field').text(err);
}
});
});
});
function readFile(file, callback){
var reader = new FileReader();
reader.onload = callback
//reader.readAsArrayBuffer(file);
reader.readAsText(file);
}
https://jsfiddle.net/68qeau3h/3/
Now, when using reader.readAsArrayBuffer(file); everything works as expected, however in my particular case, I used reader.readAsText(file); because this is how the data is retrieve for me, this is text form.
When adding these lines of code to try to convert the string into an arrayBuffer
...
var buf = new ArrayBuffer(e.target.result.length * 2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=e.target.result.length; i<strLen; i++) {
bufView[i] = e.target.result.charCodeAt(i);
}
var file = new Blob([buf], { type: 'application/pdf' });
...
This will not work and generate PDF files that the browser can't open.
So to recap, what I'm trying to do is somehow convert the result I get from reader.readAsText(file); to what reader.readAsArrayBuffer(file); produces. Because the files I'm working with, or the data im retrieving from my backend is this text form.
I have an endpoint called '/downloadUserAction' that collects data and downloads a csv file. The challenge I am having is that the file won't get downloaded when calling endpoint using a button on click function, however it'll download only when I access the endpoint directly in the browser.
Upon research, I've came across findings that concluded that you cannot use AJAX to download files. That makes sense, since when I click on my button I see the endpoint being hit and the file contents being passed in the network tab, however no file gets downloaded on the client.
This is all I'm simply doing on the javascript side using data tables button plug-in feature on my page to call my endpoint.
$(document).ready(function () {
var table = $("#userActivity").on('init.dt', function() {
}).DataTable({
dom: 'Blfrtip',
buttons: [
{
extend: 'csvHtml5',
text: 'NLP Search Download',
action: function ( e, dt, node, config ) {
$.ajax({
url : window.location + "/downloadUserAction?draw=3&search%5Bvalue%5D=NLP_SEARCH&order%5B0%5D%5Bcolumn%5D=6&order%5B0%5D%5Bdir%5D=desc"
});
}
}
],
Is there another method of calling my endpoint that will force a download on the client page?
side-note: my data table is using server side processing otherwise I would've just used datatables csv exporting button.
In modern browsers, you can prompt a download by creating a Blob with your file contents (in your case received by Ajax), creating a URL for it, and using the download attribute:
const saveData = (function () {
const a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (data, fileName) {
const blob = new Blob([data], {type: "octet/stream"}),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
const data = 'a,b,c\n5,6,7',
fileName = "my-csv.csv";
saveData(data, fileName);
JSFiddle
If your Ajax endpoint URL has the proper headers (or possibly even if it isn't as long as you use the download attribute), you can forego the Blob and Ajax and just add the URL to the link with the download attribute. Adapting #pritesh's code,
const saveData = (function () {
const a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (url, fileName) {
a.href = url;
a.download = fileName;
a.click();
};
}());
const url = 'http://www.sample-videos.com/csv/Sample-Spreadsheet-10-rows.csv', // Replace with your own URL: window.location + "/downloadUserAction?draw=3&search%5Bvalue%5D=NLP_SEARCH&order%5B0%5D%5Bcolumn%5D=6&order%5B0%5D%5Bdir%5D=desc"
fileName = "my-csv.csv";
saveData(url, fileName);
JSFiddle
Even if this is an old question, I would like to post the answer I came up with because I encountered the same problem.
There is an alternative for saving the blob directly with FileSaver.js library on client side instead of creating a link and calling the click method.
After adding the FileSaver.js, you can simply use saveAS(blob, filename) to initiate a download.
Following example is for handling a Flask server send_file(file, as_attachment=True, attachment_filename='export.csv', mimetype='text/csv') response.
function downloadCsv() {
jQuery.ajax({
async: true,
url: URL,
timeout: 5000,
type: "post",
xhrFields: {
responseType: "blob", // to avoid binary data being mangled on charset conversion
},
data: postRequestdata,
error: function (e) {
console.error(e);
},
// in jQuery 1.4+ when the success callback its executed three arguments are passed (success(data, textStatus, XMLHttpRequest))
success: function (blob, status, xhr) {
// check for a filename
var filename = "";
var disposition = xhr.getResponseHeader("Content-Disposition");
if(disposition && disposition.indexOf("filename") !== -1){
splitted = disposition.split("filename=");
filename = splitted[splitted.length-1];
saveAs(blob, filename);
}
},
});
}
Since it gets downloaded when you access the endpoint directly from the browser so what you can do is set an anchor tag inside the button and set the href attribute of the anchor tag to the url pointing to the csv file.I have created a sample example here:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<button>
Click me
</button>
</body>
</html>
If you try out this code in browser, then onclick a dialog will appear for saving the file.
In your case you need the replace the sample videos url with your own.
window.location +
"/downloadUserAction?draw=3&search%5Bvalue%5D=NLP_SEARCH&order%5B0%5D%5Bcolumn%5D=6&order%5B0%5D%5Bdir%5D=desc"
I have a form on my website that creates output for the user based on the input.
I want to create a text file with this output for the user to download (with browser download prompt, no security problems).
Is there a way to do this with Javascript/jQuery without using PHP to create the file on the server first?
Can I use some kind of Javascript object to serve as a dummy-file so that the user can download it (to solve the problem that there isn't a real txt file for the user to download from the server)?
You can achieve that by using Blob (browser support, polyfill). Check out this example by #UselessCode:
(function () {
var textFile = null,
makeTextFile = function (text) {
var data = new Blob([text], {type: 'text/plain'});
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
return textFile;
};
var create = document.getElementById('create'),
textbox = document.getElementById('textbox');
create.addEventListener('click', function () {
var link = document.getElementById('downloadlink');
link.href = makeTextFile(textbox.value);
link.style.display = 'block';
}, false);
})();
<textarea id="textbox">Type something here</textarea> <button id="create">Create file</button> <a download="info.txt" id="downloadlink" style="display: none">Download</a>
I have one download button created in JavaScript that links to particular file.
var strDownloadButton = "<br/><INPUT type="button" value="Download" onclick="add()"/>"
window.location.href = "/images/image1.jpg";
I have to rename the file image1 to image2 before downloading, so I use:
<a href="/images/image1.jpg" download="image2" >Download</a>
The problem is that there are 2 download buttons created (HTML5 download attribute created 1 more).
Is there any way to use the same button created by JavaScript, and refer into download attribute?
I have no idea what are you doing Brad Christie,
<a id="download" href="Chrysanthemum.jpg" download="image2" >Download</a>
document.getElementById("download").setAttribute("download", "image3")
here, you have an element that you want to download, you get the element and change its download attribute.
I'm not 100% sure it'll work, but I've done something like this before to download a resource and rename it using javascript. It does, however, mean the resource has to be on the same domain as the page otherwise you will run into a cross-domain security issue. Also, please excuse the fact that I'm using jQuery, but if you need to go without I'll let you look up how to make a cross-browser AJAX call.
With that said:
<!-- your anchor decorated with data-saveas -->
Download
<!-- wiring it up using jQuery/AJAX/Blob -->
<script type="text/javascript">
// Helper to convert AJAX response in to a BLOB
function dataToBlob(data, mimeString){
// convert data to ArrayBuffer
var buffer = new Int8Array(new ArrayBuffer(data.length));
for (var i = 0; i < data.length; i++){
buffer[i] = data.charCodeAt(i) & 0xff;
}
// http://stackoverflow.com/a/15302872/298053
try {
return new Blob([buffer],{type:mimeString});
} catch (e1) {
try {
var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder){
bb = new BlobBuilder();
bb.append([buffer.buffer]);
return bb.getBlob(mimeString);
} else if (e.name == 'InvalidStateError'){
return new Blob([buffer.buffer],{type:mimeString});
}
} catch (e2) {
}
}
return null;
}
// iterate over all the items that are marked as saveas
$('a[data-saveas]').each(function(){
var $this = $(this);
// Get the actual path and the destined name
var target = $this.prop('href'),
saveas = $this.data('saveas');
// make an ajax call to retrieve the resource
$.ajax({
url: target,
type: 'GET',
mimeType: 'text/plain; charset=x-user-defined'
}).done(function(data, textStatus, jqXHR){
var mimeString = jqXHR.getResponseHeader('Content-Type'),
blob = dataToBlob(data, mimeString);
if (blob){
// now modfy the anchor to use the blob instead of the default href
var filename = saveas,
href = (window.webkitURL || window.URL).createObjectURL(blob);
$this.prop({
'download': saveas,
'href': href,
'draggable': true
}).data({
'downloadurl': [mimeString, filename, href].join(':')
});
}
});
});
</script>
Not tested, but should work. Basically, you can go fetch the resource using jQuery and store it in to a blob with an assigned name. If it's able to do so, the link now becomes a custom-named blob resource with the provided name. if it can't the default functionality is retained and the user needs to name it his/herself.