从 Ajax 下载文件(有点)
Posted
技术标签:
【中文标题】从 Ajax 下载文件(有点)【英文标题】:Download file from Ajax (sort of) 【发布时间】:2012-12-30 23:21:35 【问题描述】:我的 GSP 中有这个 ajax 调用:
$.ajax(
url: '$request.contextPath + '/Ticket/passAll'',
type: 'POST',
data: data,
success: function()
alert("Success");
);
这是来自我的控制器操作的代码块:
response.setHeader("Content-disposition", "attachment; filename=sample.csv")
response.contentType = "application/vnd.ms-excel"
def outs = response.outputStream
def cols = [:]
tickets.each()
outs << it.ticketNo + ";" + it.subject
outs << "\n"
outs.flush()
outs.close()
我通过 $.Ajax 方法从视图中传递的数据中获取票证列表。比我将该数据格式化为 CSV 并且比我想将该数据导出为 CSV 文件但没有任何反应。数据被发送到客户端,但没有文件可供下载,因为内容配置格式不正确。我错过了什么? 我试图做类似的事情:
$.ajax(
url: '$request.contextPath + '/Ticket/passAll'',
type: 'POST',
data: aoData,
dataType: 'text',
success: function(result)
var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(result);
window.open(uri, 'tiketi.csv');
);
在控制器中我生成纯字符串,但这样我得到一个没有扩展名的文件,这是不可接受的。
我怎样才能做到这一点?谢谢。
【问题讨论】:
我建议改为创建一个隐藏的 iframe/form 并发布到它,这样当您的服务器返回 csv 时,下载将正常开始。 【参考方案1】:你不需要通过 ajax 来做。该页面不会重定向以进行文件下载。
【讨论】:
window.location.href = "/ControllerName/DownloadAsCSV?json=" + jsonStr;为我做了诀窍【参考方案2】:我猜 url 属性应该是固定的,因为你的引号是冲突的。
尝试:
$.ajax(
url: "$request.contextPath/Ticket/passAll",
type: 'POST',
data: aoData,
dataType: 'text',
success: function(result)
var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(result);
window.open(uri, 'tiketi.csv');
);
【讨论】:
无论如何,我必须同意 James Kleeh 和 Gregg 的观点,实际上没有必要通过 ajax 调用来做到这一点。 为什么我的文件名不是tiketi.csv
而是随机名称?
@Phoenix tiketi.csv
是问题的一部分,不确定您在这里问什么?【参考方案3】:
据我所知,不可能通过 AJAX 触发文件下载。 相反,您可以这样做(例如使用 jQuery):
function downloadComplete() hideSpinner();
function downloadStart() showSpinner();
function download()
downloadStart()
var urlParams = data // or e.g. $(form).serialize()
var downloadUrl = "$request.contextPath/Ticket/passAll?" + urlParams
$("#download-iframe").remove()
$('<iframe style="display:none" id="download-iframe" src="' + downloadUrl + '" onreadystatechange="downloadComplete()" onload="downloadComplete()">').appendTo('body');
您可能会遇到问题,因为它是一个 GET 请求:“安全”或太多参数。 不过正常情况下应该没问题的。
【讨论】:
你能验证这是否有效吗?我喜欢这个答案,但我应该怎么做才能让微调器消失?现在微调器显示并下载文件,仅此而已。微调器停留在屏幕上。【参考方案4】:我在这方面有点晚了,但偶然发现它做了一些研究。这个解决方案有点长,是从这里回答的各种问题拼凑而成的。我认为这是对这个问题的直接回答,并且我可以在应用程序中使用它。
<script>
function getCSV()
console.log("in get csv");
$.ajax(
url: "<url string>",
dataType: 'json',
type: "post",
data: ,
success: function (data)
console.log(data);
downloadCSV(filename: "<filename.csv", data: data.<array from
backend call>);
,
error: function ()
);
function downloadCSV(args)
var data, filename, link;
var csv = convertArrayOfObjectsToCSV(
data: args.data
);
if (csv == null) return;
filename = args.filename || 'export.csv';
if (!csv.match(/^data:text\/csv/i))
csv = 'data:text/csv;charset=utf-8,' + csv;
data = encodeURI(csv);
link = document.createElement('a');
link.setAttribute('href', data);
link.setAttribute('download', filename);
link.click();
function convertArrayOfObjectsToCSV(args)
var result, ctr, keys, columnDelimiter, lineDelimiter, data;
data = args.data || null;
if (data == null || !data.length)
return null;
columnDelimiter = args.columnDelimiter || ',';
lineDelimiter = args.lineDelimiter || '\n';
keys = Object.keys(data[0]);
result = '';
result += keys.join(columnDelimiter);
result += lineDelimiter;
data.forEach(function (item)
ctr = 0;
keys.forEach(function (key)
if (ctr > 0) result += columnDelimiter;
result += item[key];
ctr++;
);
result += lineDelimiter;
);
return result;
</script>
第一个函数是一个标准的 ajax 调用,用于从后端调用中获取数据数组。接下来是创建csv。第二行调用格式化 csv 文件的第三个函数。第二个函数从 csv 创建开始,最后创建一个动态链接,该链接附加到 dom 并单击以进行下载。似乎更长,但可以与后端的标准 ajax 调用一起使用。
【讨论】:
以上是关于从 Ajax 下载文件(有点)的主要内容,如果未能解决你的问题,请参考以下文章
尝试使用 Ajax 从远程服务器下载文件,但 Codeigniter 不起作用
如何使用 jQuery Ajax 调用从 ASP.NET Web Api 下载 CSV 文件