Show a pdf stream in a new window

2019-01-18 04:18发布

问题:

I'm generating in a server a PDF document that I want to show then in the client. The server side looks like following:

ByteArrayOutputStream baos = generatePDF();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=file.pdf");
response.setContentLength(baos.size());
baos.writeTo(response.getOutputStream());

In the client, I have the following code to get retrieve the PDF:

$.ajax({
    type: "POST",
    url: url,
    data: {"data": JSON.stringify(myData)},
    success: function(data, textStatus, jqXHR) {
        window.open("data:application/pdf," + escape(data));
    },
    error: function(jqXHR) {
        showError("...");
    }
});

It looks well, the new window is opened, but the PDF is not shown. It always appears an empty document.

Nevertheless, if the client looks like following, it works fine:

var form = $("<form target='_blank'>").attr({
    action : myURL,
    method : "POST"
});
var input1 = $("<input type='hidden'>").attr({
    "name": "data",
    value: JSON.stringify(myData)
});

form.append(input1);
$("body").append(form);
form.submit();
form.remove();

But I can't use the second way cause I need to manage the errors, and I can't do it using form.submit().

Any idea about what's happening with the PDF?

回答1:

You can get base64 string of your pdf stream and pass it to response.

And your method change

$.ajax({
    type: "POST",
    url: url,
    data: {"data": JSON.stringify(myData)},
    success: function(data, textStatus, jqXHR) {
        var pdfWin= window.open("data:application/pdf;base64, " + data, '', 'height=650,width=840');
        // some actions with this win, example print...
    },
    error: function(jqXHR) {
        showError("...");
    }
});


回答2:

Try using:

dataType: "application/pdf",
success: function(data, textStatus, jqXHR) {
    window.open(escape(data), "Title", "");
},


回答3:

I couldn't do this async, but this js returns the attachment ok for me:

$('<iframe src="url"></iframe>').appendTo('body').hide();

The browser then fires a save/view popup, which is fine for my requirements; no error handling though.

I think with your server side, you might want to return it as inline e.g. response.setHeader("Content-Disposition", "inline; filename=file.pdf");

You're setting the content length OK, it could be the success code will be firing twice, the first time at the beginning of the stream and the second time at the end.

Do let us know if you got this working.