我正在尝试为我的网站完成一个相当简单的任务,但我不确定如何去做。我希望用户查看表格,然后点击按钮,此时用户可以将该表的内容保存为csv文件。这个请求有时会非常复杂,所以我生成一个进度页面来提醒用户。
除了实际生成csv文件之外,我发现了大多数事情。 (我使用jQuery和PHP)
点击时运行jQuery代码:
hmis_query_csv_export: function(query_name) {
$.uiLock('<p>Query Loading.</p><img src="/images/loading.gif" />')
$.get({
url: '/php_scripts/utils/csv_export.php',
data: {query_name: query_name},
success: function(data) {
$.uiUnlock();
}
});}
相关的PHP:
header("Content-type: text/x-csv");
header("Content-Disposition: attachment; filename=search_results.csv");
//
//Generate csv
//
echo $csvOutput
exit();
这样做是将文本作为PHP文件发送,但它不会生成下载。我做错了什么?
答案 0 :(得分:42)
如果您要强制下载,可以将当前页面重定向到下载链接。由于链接将生成下载对话框,因此当前页面(及其状态)将保留在原位。
基本方法:
$('a#query_name').click(function(){
$('#wait-animation').show();
document.location.href = '/php_scripts/utils/csv_export.php?query_name='+query_name;
$('#wait-animation').hide();
});
更复杂:
$('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();
});
});
在PHP脚本:
@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();
两个请求的URL必须相同才能诱使浏览器不在document.location.href
开始新的下载,而是将副本保存在缓存中。我不是很确定,但似乎很有希望。
答案 1 :(得分:5)
编辑我刚尝试使用10MB文件,似乎val()太慢而无法插入数据。 Hurrumph。
好的,所以我给了另一个去。这可能是也可能不是完全疯了!我们的想法是创建一个AJAX请求来创建数据,然后使用回调将数据插入到当前页面上的隐藏表单中,该页面具有第三个“下载”页面的操作;插入后,表单自动提交,下载页面发送标题并回显POST,等等,下载。
在原始页面上,您已经指示文件正在准备中,并且在完成时指示符已更新。
注意:此测试代码未经过广泛测试,并且没有真正的安全检查(或根本没有)。我用1.5MB的CSV文件对它进行了测试,这个文件非常合理。
<强>的index.html 强>
<a id="downloadlink" href="#">Click Me</a>
<div id="wait"></div>
<form id="hiddenform" method="POST" action="download.php">
<input type="hidden" id="filedata" name="data" value="">
</form>
<强> test.js 强>
$(document).ready(function(){
$("#downloadlink").click(function(){ // click the link to download
lock(); // start indicator
$.get("create.php",function(filedata){ // AJAX call returns with CSV file data
$("#filedata").val(filedata); // insert into the hidden form
unlock(); // update indicator
$("#hiddenform").submit(); // submit the form data to the download page
});
});
function lock(){
$("#wait").text("Creating File...");
}
function unlock(){
$("#wait").text("Done");
}
});
<强> create.php 强>
<?php
//create $data
print $data;
?>
<强>的download.php 强>
<?php
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Type: text/x-csv");
header("Content-Disposition: attachment;filename=\"search_results.csv\"");
if($_POST['data']){
print $_POST['data'];
}
?>
答案 2 :(得分:3)
实现此目的的最佳方法是使用数据URI,如下所示:
请参阅此链接以获取相关说明(特别是第3段):http://en.wikipedia.org/wiki/Data_URI_scheme
这样,您就不需要在服务器上保存任何文件,也不需要使用iframe或隐藏的表单元素或任何此类黑客。
答案 3 :(得分:1)
我认为您不能使用AJAX / JS请求进行浏览器下载。尝试使用隐藏的iframe导航到生成CSV的页面
答案 4 :(得分:0)
使用AJAX的重点是避免页面的可见重载。如果您想要下载,则需要相反的 - 来自浏览器的全新请求。我会说,只需创建一个指向php页面的简单按钮。
答案 5 :(得分:0)
为了回应和扩展其他人的说法,你无法使用AJAX真正发送文件。造成这种情况的原因之一是(有人纠正我,如果我错了,请)您当前所在的页面已经发送了其内容标题;你不能再将它们发送到同一个窗口,即使有一个AJAX请求(这是你的PHP文件试图做的)。
我之前在项目中所做的只是提供一个链接(带有target =“_ blank”或javascript重定向)到一个单独的下载PHP页面。如果您正在使用Apache,请查看mod_xsend文件。