Download Generated CSV file via Ajax
In short, you need to create an anchor, assign an object URL for the result to the href, and then call click()
on it. Additionally, your $.ajax
call will need to specify that you're expecting a blob response, as the default in jQuery is to treat the response as text. What that boils down to is code like the following:
$.ajax({
url: "@Url.Action("GenerateEventLogsReport", @ViewContext.RouteData.Values["controller"].ToString())",
method: "POST",
xhrFields: {
responseType: 'blob'
},
data: JSON.stringify(event_form_data),
contentType: "application/json",
success: function (result) {
var a = document.createElement('a');
var url = window.URL.createObjectURL(result);
a.href = url;
a.download = 'report.csv';
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
},
error: function (error) {
console.log(error);
}
});
I also have a working CodePen to demo.
Download CSV file using AJAX
If you are forcing a download, you can redirect the current page to the download link. Since the link will generate a download dialog, the current page (and its state) will be kept in place.
Basic approach:
$('a#query_name').click(function(){
$('#wait-animation').show();
document.location.href = '/php_scripts/utils/csv_export.php?query_name='+query_name;
$('#wait-animation').hide();
});
More complicated:
$('a#query_name').click(function(){
MyTimestamp = new Date().getTime(); // Meant to be global var
$('#wait-animation').show();
$.get('/php_scripts/utils/csv_export.php','timestamp='+MyTimestamp+'&query_name='query_name,function(){
document.location.href = '/php_scripts/utils/csv_export.php?timestamp='+MyTimestamp+'&query_name='+query_name;
$('#wait-animation').hide();
});
});
At PHP script:
@header("Last-Modified: " . @gmdate("D, d M Y H:i:s",$_GET['timestamp']) . " GMT");
@header("Content-type: text/x-csv");
// If the file is NOT requested via AJAX, force-download
if(!isset($_SERVER['HTTP_X_REQUESTED_WITH']) || strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') {
header("Content-Disposition: attachment; filename=search_results.csv");
}
//
//Generate csv
//
echo $csvOutput
exit();
The URL for both requests must be the same to trick the browser not to start a new download at document.location.href
, but to save the copy at the cache. I'm not totally sure about it, but seems pretty promising.
Download csv file as response on AJAX request
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
How to download the csv file by ajax
You can try this using Blob
api:
const DownloadCsv = (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);
};
}());
$.ajax({
type: "GET",
url: url,
success: function(response) {
//console.log(response);
DownloadCsv(response, 'somefilename.csv')
}
});
How to download a csv file requested through jquery/ajax from flask server
I think it's because the file's content is stored in the data
variable (of the "success" callback of $.ajax), so it's just a js variable for the browser.
I think the best (cleanest maybe?) thing you can do is wrap your .download-btn
in a <a>
tag with your download url in href
<a href="/downloadFile" target="_blank">
<button class="download-btn">Download</button>
</a>
This way "the browser itself" makes the GET request to /downloadFile
(in a new tab because of the target="_blank"
attribute), receives the stream and downloads the file (and closes tab once the download is started).
How to download CSV file from PHP script via AJAX?
Further to my comment(s), I would make the form able to submit normally or using ajax. Ajax for search, normal submit for download:
<div class="container">
<!-- Make this a proper form tag again -->
<form id="ldap-form" method="post" action="working_csv.php">
<h2><strong><p>Search the LDAP server</p></strong></h2>
<label for="location"><p>Enter your search location (ex: dc=example,dc=com)</p></label>
<input type="text" id="location" name="location" placeholder="Search Location.." />
<label for="filter"><p>Enter your search filter(s) (ex: uid=* or </p></label>
<input type="text" id="filter" name="filter" placeholder="Filter(s).." />
<input type="submit" name="search" id="search" value="Search LDAP Server" />
<input type="submit" name="download" id="download" value="Download results as CSV file" />
</form>
<!-- Response container -->
<p id="msg"></p>
</div>
<script>
$(function(){
$('input[type="submit"]').on('click', function(e){
// Stop form from submission
e.preventDefault();
// Detect button press type
let thisSubmission = $(this).attr('name');
// If the button is search, do ajax
if(thisSubmission == 'search') {
$.ajax({
type: "post",
url: $('#ldap-form').attr('action'),
data: $('#ldap-form').serialize(),
cache: false,
success: function(html){
$('#msg').html(html);
}
});
}
else {
// Just submit the form normally
$('#ldap-form').submit();
}
});
});
</script>
Related Topics
PHP Filesize Reporting Old Size
How to Access the Form's 'Name' Variable from PHP
Laravel Tokenmismatchexception in Ajax Request
How to Generate an Excel Document with Multiple Worksheets from PHP
How to Build Unlimited Level of Menu Through PHP and MySQL
In PHP, How to Detect the Execution Is from Cli Mode or Through Browser
How to Fix "Set Samesite Cookie to None" Warning
Request Headers Bag Is Missing Authorization Header in Symfony 2
How to Use Include Within a Function
Why Doesn't Var_Dump Work with Domdocument Objects, While Print($Dom->Savehtml()) Does
PHP See Only 20 Uploading Files at a Time
Parse Error: Syntax Error, Unexpected '(', Expecting ',' or ';' In
PHP Regular Expression to Match Lines Starting with a Special Character