我有一个基于jquery的单页webapp。它通过AJAX调用与RESTful Web服务进行通信。
我正在尝试完成以下任务:
- 将包含JSON数据的POST提交到REST URL。
- 如果请求指定JSON响应,则返回JSON。
- 如果请求指定PDF / XLS / etc响应,则返回可下载的二进制文件。
我现在有1&2,并且客户端jquery应用通过基于JSON数据创建DOM元素来在网页中显示返回的数据。从Web服务的角度来看,我也有#3工作,这意味着如果给出正确的JSON参数,它将创建并返回一个二进制文件。但是我不确定在客户端JavaScript代码中处理#3的最佳方法。
是否可以通过这样的ajax调用取回可下载文件?如何让浏览器下载并保存文件?
$.ajax({
type: "POST",
url: "/services/test",
contentType: "application/json",
data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
dataType: "json",
success: function(json, status){
if (status != "success") {
log("Error loading data");
return;
}
log("Data loaded!");
},
error: function(result, status, err) {
log("Error loading data");
return;
}
});
服务器使用以下标头进行响应:
Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)
另一个想法是生成PDF并将其存储在服务器上,并返回包含文件URL的JSON。然后,在ajax成功处理程序中发出另一个调用,以执行以下操作:
success: function(json,status) {
window.location.href = json.url;
}
但这意味着我需要对服务器进行多次调用,并且服务器需要构建可下载文件,将它们存储在某个地方,然后定期清理该存储区域。
必须有一种更简单的方法来完成此任务。有想法吗?
编辑:审查$ .ajax的文档后,我看到响应数据类型只能是之一xml, html, script, json, jsonp, text
,因此我猜测没有办法直接使用ajax请求下载文件,除非我将二进制文件嵌入到@VinayC答案中建议的数据URI方案(我不想这样做)。
所以我想我的选择是:
不使用ajax,而是提交一个表单发布,并将我的JSON数据嵌入到表单值中。可能需要弄乱隐藏的iframe等。
不使用ajax,而是将我的JSON数据转换为查询字符串以构建标准的GET请求,并将window.location.href设置为此URL。可能需要在我的点击处理程序中使用event.preventDefault(),以防止浏览器从应用程序URL更改。
使用上面我的其他想法,但是在@naikus答案中的建议得到了增强。提交带有一些参数的AJAX请求,该参数使Web服务知道通过ajax调用正在调用该请求。如果从ajax调用中调用了Web服务,则只需将带有URL的JSON返回到生成的资源即可。如果直接调用资源,则返回实际的二进制文件。
我想得越多,我越喜欢最后一个选择。这样,我可以获取有关请求的信息(生成时间,文件大小,错误消息等),并且可以在开始下载之前根据该信息进行操作。缺点是服务器上的额外文件管理。
还有其他方法可以做到这一点吗?我应该知道这些方法的利弊吗?
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url);
获得相同结果的简单方法。将标题放在php文件中。无需发送任何AJAX或get请求