POST到服务器,接收PDF,交付给用户w / jQuery

我有一个用户点击获取PDF的链接。 在jQuery中,我创build一个POST ajax调用服务器来获取PDF。 PDF带给我正确的内容头等,这通常会导致浏览器打开Reader插件,或允许用户保存PDF。

由于我得到PDF的w / ajax调用,我不知道如何处理我在OnSuccesscallback中获得的数据。 如何将我收到的数据提供给浏览器,并允许其使用PDF响应来执行默认操作?

你根本不需要jQuery。 通常通过表单提交您的POST,并在服务器端添加HTTP标头

 Content-Disposition: attachment; filename="whatever.pdf" 

浏览器将执行其默认的事情。

或者,如果您想要更加小心地报告在PDF生成过程中可能发生的任何错误,您可以执行此操作。 用jQuery将你的参数发送到你的服务器。 在服务器上,生成二进制内容并将其caching在某个地方几分钟,可以通过放入用户会话的键访问,并向页面返回“成功”的Ajax响应(或者如果出现错误,则返回“错误”响应)。 如果页面取回成功响应,则可以立即执行如下操作:

 window.location = "/get/my/pdf"; 

服务器然后返回caching的PDF内容。 请确保包含Content-Disposition标题,如上所述。

看看 – jQuery插件用于请求类似Ajax的文件下载

整个plugin只有大约30行代码(包括注释)。

这个调用与jquery ajax调用非常相似。

 $.download('/export.php','filename=myPDF&format=pdf&content=' + pdfData ); 

当然,你必须像在任何这样的下载中一样,在服务器端设置内容types和内容处理标题。

在Java中,我会做这样的事情

 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename="exported.pdf"); 

提到“用于请求类似Ajax的文件下载的jQuery插件”的答案让我朝着正确的方向前进,但是它并不完全适用于我的情况,因为我有一个复杂的对象和对象数组作为我的search条件/过滤数据。 我想我会分享我的代码,以防其他人也遇到这种情况。

 $.download = function (url, data, method) { if (url && data) { //convert the data object into input HTML fields var inputs = ''; var convertToInput = function (key, keyStr, obj) { if (typeof obj === 'undefined') { return; } else if (typeof obj === "object") { for (var innerKey in obj) { if (obj.hasOwnProperty(innerKey)) { var innerKeyStr = ''; if (keyStr === '') { innerKeyStr = innerKey.toString(); } else { innerKeyStr = keyStr + "[" + innerKey.toString() + "]"; } convertToInput(innerKey, innerKeyStr, obj[innerKey]); } } return; } else if ($.isArray(obj)) { obj.forEach(function (item) { convertToInput(key, keyStr + "[]", item); }); return; } inputs += "<input type='hidden' name='" + keyStr + "' value='" + obj + "' />"; }; convertToInput(null, '', data); //send request jQuery('<form action="' + url + '" method="' + (method || 'post') + '">' + inputs + '</form>').appendTo('body').submit().remove(); }; }; $.download('/api/search?format=csv', searchData, 'POST'); 

它可能没有太大的区别,但是为了提供一些上下文,我已经有一个JavaScript和敲除UI调用WebAPI,MVC4和nHibernate。 查询string的“format = csv”部分触发MediaTypeFormatter将返回的模型转换为CSV文件types。 如果我把它closures,那么我从API获取模型,并可以填充一个Slick网格来显示。

我有同样的问题,但最重要的是使用RESTFUL webservice为此,并有一个复杂的数据对象,我必须发布。

我的解决scheme:像jQuery插件我build立一个临时forms并提交。 但我发送数据对象作为参数与JSON内容(我在这里使用AngularJS但它也应该与jQuery.param() 。)

使用Javascript:

 $('<form target="_blank" action="' + appConstants.restbaseurl + '/print/pdf" method="POST">' + "<input name='data' value='" + angular.toJson($scope.versicherung) + "' />" + '</form>').appendTo('body').submit().remove(); 

在服务器端,我们使用带有JACKSON提供程序的CXF REST Service

springconfiguration:

 <jaxrs:server id="masterdataService" address="/"> <jaxrs:serviceBeans> <ref bean="printRestServiceBean" /> </jaxrs:serviceBeans> <jaxrs:providers> <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" /> <bean class="de.controller.ExceptionHandler" /> </jaxrs:providers> </jaxrs:server> 

在控制器中,我提取param并将其转换回Java Pojo:

 package de.controller; import javax.ws.rs.Consumes; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.codehaus.jackson.map.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; @Path(Constants.PRINT_PATH) @Consumes({ MediaType.APPLICATION_JSON, "application/x-www-form-urlencoded"}) @Produces("application/pdf; charset=UTF-8") public class PrintRestController { @Autowired private PrintService printService; @POST @Produces("application/pdf") @Path("/pdf") public Response getPDF(@FormParam("data") String data) { return printService.getPDF(json2Versicherung(data)); } private Versicherung json2Versicherung(String data) { Versicherung lVersicherung = null; try { ObjectMapper mapper = new ObjectMapper(); lVersicherung = mapper.readValue(data, Versicherung.class); } catch(Exception e) { LOGGER.error("PrintRestController.json2Versicherung() error", e); } return lVersicherung; } } 

在PrintService中,我构buildpdf二进制文件和响应:

 @Override public Response getPDF(Versicherung pVersicherung) { byte[] result = ... //build the pdf from what ever ResponseBuilder response = Response.ok((Object) result); response.header("Content-Disposition", "inline; filename=mypdf.pdf"); return response.build(); } 

这个解决scheme适用于所有的浏览器(即使IE9无法处理数据url),在平板电脑和智能手机上,它与popup式窗口拦截器没有问题

用于请求类似Ajax的文件下载的jQuery插件基本上是创build一个表单,将后期数据添加为隐藏字段,将其添加到页面主体,提交并删除它。

在我的情况下,我没有一个表格,只有大量的数据发布,因为它是。 这是为以下解决scheme。 在服务器端,我可以通过从请求中读取“data”参数并对其进行URI解码来获取数据。

 function postAndDownload(url, data) { encodedData = encodeURIComponent(data); $("<form>") .attr("action", url) .attr("method", "post") .append( $("input") .attr("type", "hidden") .attr("name", "data") .attr("value", encodedData) ) .appendTo("body") .submit() .remove(); }; 

我不明白你为什么要一个文件下载url的ajax请求! 但是,如果它更像客户端本身生成一些内容下载 – 使用数据uri。 适用于Chrome和Firefox 20+。 Safari和IE不是! 如果Flash被允许,你可以使用下载器。

读完你的代码后,我看到你想发送一堆参数。 那么除非查询string太长(IE8-有2083的限制),为什么不简单地使用具有适当的URL的锚呢?

  $('a.export-csv').click( function (evt){ linkEl.attr('href','/export?' + encodeURIComponent(formQueryString())); return true; }); 

以上允许您在默认事件(点击)发生之前更改URL。

我认为最好的办法是在下载文件夹中创build一个临时pdf文件,然后使用带有iframe的popup窗口来加载文件。铬会立即加载,但我想对于其他变体Acrobat阅读器必须安装以查看pdf但是你也可以使用FlashPaper 🙂