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

发布到服务器,接收PDF,交付给用户w/jQuery,jquery,ajax,pdf,post,Jquery,Ajax,Pdf,Post,我有一个链接,用户点击该链接可以获得PDF。在jQuery中,我创建一个对服务器的POST ajax调用来获取PDF。我收到的PDF带有正确的内容标题等,通常会导致浏览器打开阅读器插件,或允许用户保存PDF 由于我得到的是带有ajax调用的PDF,我不确定如何处理在OnSuccess回调中得到的数据。如何将接收到的数据提供给浏览器,并允许其使用PDF响应执行默认操作?请查看- 整个插件只有大约30行代码(包括注释) 该调用与jqueryajax调用非常相似 $.download('/export

我有一个链接,用户点击该链接可以获得PDF。在jQuery中,我创建一个对服务器的POST ajax调用来获取PDF。我收到的PDF带有正确的内容标题等,通常会导致浏览器打开阅读器插件,或允许用户保存PDF

由于我得到的是带有ajax调用的PDF,我不确定如何处理在OnSuccess回调中得到的数据。如何将接收到的数据提供给浏览器,并允许其使用PDF响应执行默认操作?

请查看-

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

该调用与jqueryajax调用非常相似

$.download('/export.php','filename=myPDF&format=pdf&content=' + pdfData );
当然,您必须在服务器端设置内容类型和内容处置头,就像任何此类下载一样

在java中,我会这样做

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

您根本不需要jQuery。正常情况下,只需通过表单提交帖子,然后在服务器端添加HTTP头

Content-Disposition: attachment; filename="whatever.pdf"
浏览器将执行其默认操作

或者,如果您想更仔细地报告PDF生成过程中可能发生的任何错误,可以这样做。使用jQuery将参数发布到服务器。在服务器上,生成二进制内容并将其缓存在某个地方几分钟,可通过用户会话中输入的密钥访问,然后向页面返回“成功”Ajax响应(或者如果出现错误,则返回“错误”响应)。如果页面返回成功响应,它可以立即执行以下操作:

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

然后服务器返回缓存的PDF内容。请确保包含内容处置标题,如上所述。

我认为最好是在下载文件夹中创建一个临时pdf文件,然后使用带有iframe的弹出窗口加载该文件。。chrome将立即加载它,但我认为对于其他变体,必须安装Acrobat reader才能查看pdf,但您也可以使用抽认纸:)

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

$.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');
$.download=函数(url、数据、方法){
如果(url和数据){
//将数据对象转换为输入HTML字段
var输入=“”;
var CONVERTOINPUT=功能(键、键TR、obj){
如果(obj的类型==‘未定义’){
返回;
}else if(对象类型==“对象”){
for(obj中的var innerKey){
if(对象hasOwnProperty(innerKey)){
var innerKeyStr='';
如果(keyStr==''){
innerKeyStr=innerKey.toString();
}否则{
innerKeyStr=keyStr+“[”+innerKey.toString()+“]”;
}
convertToInput(innerKey,innerKeyStr,obj[innerKey]);
}
}
返回;
}否则如果($.isArray(obj)){
目标forEach(功能(项目){
转换输入(键,键TR+“[]”,项);
});
返回;
}
输入+=”;
};
转换输入(空,,,数据);
//发送请求
jQuery(“”+inputs+“”).appendTo('body').submit().remove();
};
};
$.download('/api/search?format=csv',searchData',POST');

这可能没有多大区别,但为了提供一些上下文,我有一个javascript和敲除UI调用WebAPI、MVC4和nHibernate。查询字符串的“format=csv”部分触发MediaTypeFormatter将返回的模型转换为csv文件类型。如果我不这样做,那么我就可以从API中获取模型,并可以填充一个光滑的网格来显示。

我不明白为什么您希望ajax请求文件下载url!但若它更像是客户端本身生成一些内容供下载,那个么就使用一个数据uri。适用于Chrome和Firefox 20+。狩猎旅行,不!如果允许闪存,您可以使用下载器


啊在读了你的代码之后,我看到你想要发送一堆参数。除非查询字符串变得太长(IE8-限制为2083),为什么不简单地使用带有正确url的锚

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

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

我也遇到了同样的问题,但最重要的是使用了
RESTFUL Web服务,并且有一个复杂的数据对象,我必须发布它

我的解决方案: 像jQuery插件一样,我构建了一个临时公式并提交它。但是我将数据对象作为包含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();
在控制器中,我提取了参数并将其转换回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中,我构建pdf二进制文件和响应:

@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();
}

此解决方案适用于所有浏览器(即使IE9无法处理数据url),也适用于平板电脑和智能手机,并且PopupLocker没有问题

请求类似Ajax的文件下载的jQuery插件本质上是创建表单,将post数据添加为隐藏字段,将其添加到页面主体,提交并删除它

在我的例子中,我没有表单,只有一大块数据要按原样发布。这就产生了下面的解决方案。在服务器端,我可以通过简单地从请求中读取“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();
};
函数postAndDownload(url、数据){
encodedData=encodeURIComponent(数据);
$("")
.attr(“操作”,url)
.attr(“方法”、“职位”)
.附加(
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();
};