How can I download the textarea value/contents when I click a button? It should act like PHP:
<?php
$file = 'proxies.txt';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
I just can't find any way on here to do it. I don't want it to make a href to click a second time to download. I just want to click a button and it will download a txt file containing the textarea's contents.
My current code that wont work:
$('#test').click(function() {
contentType = 'data:application/octet-stream,';
uriContent = contentType + encodeURIComponent($('#proxiescontainer').val());
$(this).setAttribute('href', uriContent);
});
Explanation:
#test is the a tag wrapping the button;
#proxiescontainer is the textarea itself;
So how can I get it to be a onClick download of the textarea's contents?
My AJAX:
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "grab.php", true);
xhttp.send();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var t = $('#proxiescontainer').scrollTop(), $d2 = $('#proxiescontainer').replaceWith('<button type="button" id="download" class="form-control button">Download</button><textarea id="proxiescontainer" class="form-control message-input" style="height: 250px!important;">' + xhttp.responseText + '</textarea>');
if (t){ $('#proxiescontainer').scrollTop(t + $d2.outerHeight()); }
}
}
Using existing js setAttribute() is not a jQuery method ; to use on DOM element remove jQuery() wrapper
$('#test').click(function() {
contentType = 'data:application/octet-stream,';
uriContent = contentType + encodeURIComponent($('#proxiescontainer').val());
this.setAttribute('href', uriContent);
});
alternatively using Blob createObjectURL() , download attribute
$("button").click(function() {
// create `a` element
$("<a />", {
// if supported , set name of file
download: $.now() + ".txt",
// set `href` to `objectURL` of `Blob` of `textarea` value
href: URL.createObjectURL(
new Blob([$("textarea").val()], {
type: "text/plain"
}))
})
// append `a` element to `body`
// call `click` on `DOM` element `a`
.appendTo("body")[0].click();
// remove appended `a` element after "Save File" dialog,
// `window` regains `focus`
$(window).one("focus", function() {
$("a").last().remove()
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<textarea></textarea>
<button>download</button>
Related
I create a PHP and ajax codes to create CSV file and download it when click a button. The PHP codes work fine, and for ajax I modify and set js codes according to Handle file download from ajax post all works good. but the downloaded csv file is empty while the file in custom file is correct. I use this codes in custom wordpress plugin.
function _exe_export_vendor_products(){
$current_user_id = esc_sql($_POST['c_user_id']);
$arg = array(
'limit' => 20,
'author' => $current_user_id
);
$product_list = wc_get_products($arg);
$title_array[] = array('ID', 'name', 'Price', 'SalePrice');
foreach($product_list as $_list){
$data_array[] = array($_list->get_id(), $_list->get_name(), $_list->get_price(), $_list->get_sale_price());
}
$final_array = array_merge($title_array, $data_array);
date_default_timezone_set("Asia/Tehran");
$current_date = date('Y-m-d-H-i');
$filename = "export-" . $current_user_id . "-" . $current_date . ".csv";
$f = fopen('https://sitename.com/export-import/' . $filename, 'w');
$delimiter=";";
foreach($final_array as $final_item){
fputcsv($f, $final_item, $delimiter);
}
fseek($f, 0);
header('Content-Type: text/csv; charset=UTF-8' );
header('Content-Encoding: UTF-8');
header('Content-Disposition: attachment; filename="'.$filename.'";');
readfile($filename);
fclose($f);
}
and JS codes:
jQuery.ajax({
type: "POST",
url: Ajax_object_dokan.ajax_url,
data:{
action: '_dokan_export_vendor',
c_user_id : current_user_id
},
xhrFields:{
responseType: 'blob'
},
success: function(blob, status, xhr){
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if(disposition && disposition.indexOf('attachment') !== -1){
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
if (filename) {
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});
I create file in https://sitename.com/export-import/filename.csv while the create tag a in JS has link to https://sitename.com/59360c8b-22a5-462b-9d7e-240e54a0c094.
How can I access to correct link to download file with ajax?
There are several issues in your code:
You use fopen() to access a URL with w mode. It can't work. You can only access a URL for reading.
Just use a path on the filesystem, for example:
$f = fopen($_SERVER['DOCUMENT_ROOT'] . '/export-import/' . $filename, 'w');
You call readfile() with just the file name, not the full path.
You call readfile() on the file before closing it. It may work but it's better to call fclose() first.
And you don't need to call fseek().
You set the Content-Encoding: UTF-8 header. That header is used to indicate compression (e.g. gzip), not
the character encoding. Remove it.
Also note that you don't need AJAX to download a file. You can just submit a form. All that complicated JS code is unnecessary.
I use PhpSpreadsheet for export mysql data in this way:
Page 1:
button trigger window.open to page with script for export
window.open('/export.php?data.., '_self');
Page 2 (export.php):
Whole system for export and php://output
ob_end_clean();
ob_start();
$objWriter->save('php://output');
exit;
Can I somehow understand if the export page has finished?
I need this for trigger a overlay.
What i have tried?
Looking in stackoverflow I tried this solution but it didn't work:
overlay.style.display = "block";
let myPopup = window.open('/export.php?data.., '_self');
myPopup.addEventListener('load', () => {
console.log('load'); //just for debug
overlay.style.display = "none";
}, false);
This will execute an ajax request which will result in a download without refreshing the page with jQuery
<button id='download'>Download Spreadsheet</button>
<form method='get' action='/export.php?' id='hiddenForm'>
<input type='hidden' name='foo' value='bar' />
<input type='hidden' name='foo2' value='bar2' />
</form>
$(document).on('click', '#download', function (e) {
e.preventDefault();
$('#hiddenForm').submit();
});
Make sure your PHP outputs the correct content type
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
Another Option
Based on this post, there isn't an api available to truly detect the loading of a javascript window object across all different browsers. This method uses a defer callback and postMessage approach to acommodate most modern browsers.
function defer (callback) {
var channel = new MessageChannel();
channel.port1.onmessage = function (e) {
callback();
};
channel.port2.postMessage(null);
}
var awaitLoad = function (win, cb){
var wasCalled = false;
function unloadListener(){
if (wasCalled)
return;
wasCalled = true;
win.removeEventListener("unload", unloadListener);
win.removeEventListener("pagehide", unloadListener);
// Firefox keeps window event listeners for multiple page loads
defer(function (){
win.document.readyState;
// IE sometimes throws security error if not accessed 2 times
if (win.document.readyState === "loading")
win.addEventListener("load", function loadListener(){
win.removeEventListener("load", loadListener);
cb();
});
else
cb();
});
};
win.addEventListener("unload", unloadListener);
win.addEventListener("pagehide", unloadListener);
// Safari does not support unload
}
w = window.open();
w.location.href="/export.php?data=foo";
awaitLoad(w, function (){
console.log('got it')
});
I will give +1 to #Kinglish answer because awaitLoad function can help, in my case i used ajax instead with this method Link answer
What is it about?
Create an Ajax call with json type to export page and use done to catch JSON
like:
overlay.style.display = "block"; //active overlay
$.ajax({
url: "/export.php",
type: "GET",
dataType: 'json',
data: {
data: data
}
}).done(function(data) {
var $a = $("<a>");
$a.attr("href", data.file);
$("body").append($a);
$a.attr("download", "nameoffile.xls");
$a[0].click();
$a.remove();
overlay.style.display = "none"; //deactive overlay
});
In PHP page catch php://output with ob_get_contents then return json like:
$xlsData = ob_get_contents();
ob_end_clean();
$response = array(
'op' => 'ok',
'nomefile' => 'nameofile',
'file' => "data:application/vnd.ms-excel;base64,".base64_encode($xlsData)
);
die(json_encode($response));
The last step is create, click and remove a fake link.
I have tried to search the solution but could not get any relevant answer. I want to close the current popup once File download popup opens in the browser. For example, in the source code below if i write "window.close()" after ajax request then file download popup is never shown.
But once i remove this line then file download works but how would i close the current popup?
My use case is:
main.php
<script>
window.open('popup.php','redirect','width=500,height=500');
</script>
popup.php
<body>
<script type="text/javascript" src="jquery-1.8.3.min.js"></script>
<script>
var url = 'download.php';
var output_type = 'xls';
params = "function=execute_cache&output="+output_type;
$.ajax({
type: "POST",
url: url,
data: params,
success: function(response, status, request) {
var disp = request.getResponseHeader('Content-Disposition');
if (disp && disp.search('attachment') != -1) {
var form = $('<form method="POST" action="' + url + '">');
$.each(params, function(k, v) {
form.append($('<input type="hidden" name="' + k +
'" value="' + v + '">'));
});
$('body').append(form);
form.submit();
}
}
});
window.close();
</script>
</body>
download.php
<?php
$handle = fopen("file.txt", "w");
fwrite($handle, "text1.....");
fclose($handle);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename('file.txt'));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('file.txt'));
readfile('file.txt');
exit;
Note: I can not use setTimeout function to auto close popup because i do not know in how much time file will be downloaded. So i can not give a maximum time. The code shown in download.php is not an actual code. Actually, i would fetch huge data and generate XLS.
I just want to get current popup closed automatically as soon as File download popup is shown to user to download the file.
use promise to do such async calls. learn more about it https://www.sitepoint.com/overview-javascript-promises/
also give a id to window.open like
windowPopup = window.open('popup.php','redirect','width=500,height=500');
and use
windowPopup.close();
var windowPopup = window.open('popup.php','redirect','width=500,height=500');
function callRequest () {
return new Promise(function (resolve, reject) {
var url = 'download.php';
var output_type = 'xls';
var params = "function=execute_cache&output="+output_type;
var xhr = new XMLHttpRequest();
xhr.open('POST', url, param);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
var disp = request.getResponseHeader('Content-Disposition');
if (disp && disp.search('attachment') != -1) {
var form = $('<form method="POST" action="' + url + '">');
$.each(params, function(k, v) {
form.append($('<input type="hidden" name="' + k +
'" value="' + v + '">'));
});
$('body').append(form);
setTimeout(function(){
form.submit();
resolve(true);
}, 1000);
}
} else {
reject(false);
}
};
xhr.onerror = function () {
reject(false);
};
xhr.send();
});
}
callRequest()
.then(function (res) {
console.log('result : ', res);
if(res) {
windowPopup.close();
}
})
.catch(function (err) {
console.error('error : ', err);
});
I am trying to download files using Ajax and show a custom download progress bar.
The problem is I can't understand how to do so. I wrote the code to log the progress but don't know how to initiate the download.
NOTE: The files are of different types.
Thanks in advance.
JS
// Downloading of files
filelist.on('click', '.download_link', function(e){
e.preventDefault();
var id = $(this).data('id');
$(this).parent().addClass("download_start");
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest();
// Handle Download Progress
xhr.addEventListener("progress", function (evt) {
if(evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
}
}, false);
return xhr;
},
complete: function () {
console.log("Request finished");
}
})
});
HTML and PHP
<li>
<div class="f_icon"><img src="' . $ico_path . '"></div>
<div class="left_wing">
<div class="progressbar"></div>
<a class="download_link" href="#" id="'.$file_id.'"><div class="f_name">' . $full_file_name . '</div></a>
<div class="f_time_size">' . date("M d, Y", $file_upload_time) . ' ' . human_filesize($file_size) . '</div>
</div>
<div class="right_wing">
<div class="f_delete">
<a class="btn btn-danger" href="#" aria-label="Delete" data-id="'.$file_id.'" data-filename="'.$full_file_name.'"><i class="fa fa-trash-o fa-lg" aria-hidden="true" title="Delete this?"></i>
</a>
</div>
</div>
</li>
If you want to show the user a progress-bar of the downloading process - you must do the download within the xmlhttprequest. One of the problems here is that if your files are big - they will be saved in the memory of the browser before the browser will write them to the disk (when using the regular download files are being saved directly to the disk, which saves a lot of memory on big files).
Another important thing to note - in order for the lengthComputable to be true - your server must send the Content-Length header with the size of the file.
Here is the javascript code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a1" data-filename="filename.xml">Click to download</div>
<script>
$('#a1').click(function() {
var that = this;
var page_url = 'download.php';
var req = new XMLHttpRequest();
req.open("POST", page_url, true);
req.addEventListener("progress", function (evt) {
if(evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
}
}, false);
req.responseType = "blob";
req.onreadystatechange = function () {
if (req.readyState === 4 && req.status === 200) {
var filename = $(that).data('filename');
if (typeof window.chrome !== 'undefined') {
// Chrome version
var link = document.createElement('a');
link.href = window.URL.createObjectURL(req.response);
link.download = filename;
link.click();
} else if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE version
var blob = new Blob([req.response], { type: 'application/force-download' });
window.navigator.msSaveBlob(blob, filename);
} else {
// Firefox version
var file = new File([req.response], filename, { type: 'application/force-download' });
window.open(URL.createObjectURL(file));
}
}
};
req.send();
});
</script>
And here is an example for the php code you can use:
<?php
$filename = "some-big-file";
$filesize = filesize($filename);
header("Content-Transfer-Encoding: Binary");
header("Content-Length:". $filesize);
header("Content-Disposition: attachment");
$handle = fopen($filename, "rb");
if (FALSE === $handle) {
exit("Failed to open stream to URL");
}
while (!feof($handle)) {
echo fread($handle, 1024*1024*10);
sleep(3);
}
fclose($handle);
Note that I added a sleep to simulate a slow connection for testing on localhost.
You should remove this on production :)
I have a script that pops up a page in a new window, the data are recieved via an AJAX call.
the code is:
$scope.downloadExcell = function () {
$http.post('/Monitor/DownloadExcell', { model: $scope.formModel })
.success(function (data) {
var html = "<!DOCTYPE html><html><head><meta http-equiv="
+"'Content-type' content='application/vnd.ms-excel' />"
+"<meta http-equiv='content-disposition' content='attachment; filename=fegc.xls' />"
+"<title>_excell</title></head><body>";
html = html + "<table style='width:100%;' >";
html = html + "<tr>";
for (prop in data[0]) {
html = html + "<td>" + prop + "</td>";
}
html = html + "</tr>";
for (key in data) {
html = html + "<tr>";
for (prop in data[key]) {
html = html + "<td>" + data[key][prop] + "</td>";
}
html = html + "</tr>";
}
html = html + "</table>" + "</body>" + "</html>";
var w = window.open();
$(w.document.body).html(html);
});
Now, I want the browser to download the page as an .xlsx file
when it's loaded instead of rendering it.
is it possible? Can't figure this one out.
I tried with the meta but they just get ignored.
Thank you!
INFO: this is an ASP.NET MVC WEB APPLICATION
You can do the following trick. You create a <a> tag and you give him a custom object URL as its href attribute.
This will cause the <a> to force download with the mimetype set.
You can put your HTML in the content variable.
var name ='excel-file.xlsx'; // The name of the file to be downloaded
var content = 'data'; // The contents of the file
var mimetype = 'application/vnd.ms-excel'; // The mimetype of the file for the browser to handle
// Add the <a> in the end of the body. Hide it so that it won't mess with your design.
$('body').append('<a class="download-trigger" style="display:none;"></a>');
var a = $('.download-trigger')[0];
a.href = window.URL.createObjectURL(new Blob([content], {
type: mimetype
}));
a.download = name;
a.textContent = 'Download';
a.click();
Note: You only need to append the <a> to the <body> only once, not every time you execute this code.
Here is a demo http://jsfiddle.net/5dyunv6w/ (download will start when you open the page)
You can only do that on a with a server side language,
// PHP
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header("Content-Type: application/vnd.ms-excel; charset=utf-8");
header("Content-disposition: attachment; filename=filtro.xls");
Use this funtion to download file.
function SaveToDisk(fileURL, fileName) {
//alert("yes i m working");
// for non-IE
if (!window.ActiveXObject) {
var save = document.createElement('a');
save.href = fileURL;
save.target = '_blank';
save.download = fileName || 'unknown';
var evt = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': false
});
save.dispatchEvent(evt);
(window.URL || window.webkitURL).revokeObjectURL(save.href);
}
// for IE < 11
else if ( !! window.ActiveXObject && document.execCommand) {
var _window = window.open(fileURL, '_blank');
_window.document.close();
_window.document.execCommand('SaveAs', true, fileName || fileURL)
_window.close();
}
}