15

I'm trying to display a PDF(which is created in the server side and pass to the client side as a web stream) through an AJAX call. My code is given below:

jQuery.ajax({
    type: "POST",
    processData: false,
    url: "aaaa.p?name=pdf",
    data: inputxml,
    contentType: "application/xml; charset=utf-8",
    success: function(data)
    {
      // here the data is the PDF stream i'm getting from the server side. 

    }
});

The 'inputxml' is containing input parameters for the server to create the PDF. and the 'data' in the success function containing PDF stream. Is there any way to open the PDF file on the browser inside the success function of the AJAX call with-out doing any page submit? In the server side the PDF is not physically generated also. Highly appreciate your help....

Tom van Enckevort
  • 4,170
  • 1
  • 25
  • 40
Knissanka
  • 207
  • 1
  • 3
  • 12

4 Answers4

16

Why do you load it via AJAX? Why don't you load it in an IFRAME that you generate when you need it. The standard browsers plugin will display it then inside that Iframe.

$('#link').click(function(e) {
    e.preventDefault(); // if you have a URL in the link
    jQuery.ajax({
        type: "POST",
        processData: false,
        url: "aaaa.p?name=pdf",
        data: inputxml,
        contentType: "application/xml; charset=utf-8",
        success: function(data)
        {
            var iframe = $('<iframe>');
            iframe.attr('src','/pdf/yourpdf.pdf?options=first&second=here');
            $('#targetDiv').append(iframe);
        }
    });
});
Zim84
  • 3,404
  • 2
  • 35
  • 40
  • Thanks for the quick respond. Can you give me some working example? – Knissanka Jan 28 '13 at 09:44
  • I added something. inputxml must be converted to parameters for the URL request, but that shouldn't be a problem. – Zim84 Jan 28 '13 at 09:51
  • Thanks for the reply, but the issue is the inputxml is bit large and containing lot of data. I don't think its possible to put it to the URL as a query string. – Knissanka Jan 28 '13 at 10:47
  • Then you can send the inputxml via AJAX and when the server tells you everything is ok you can insert the iframe. In the comment from a different post you said that the xmldata and the pdf aren't correlated, so this should work. – Zim84 Jan 28 '13 at 10:56
  • 2
    yes. instead of iframe.attr('src','/pdf/yourpdf.pdf?options=first&second=here'); Can I add the returned value from the AJAX success function to the iFrame.? (instead of specifying the src, because the respond not containing any URL, but only the PDF stream) – Knissanka Jan 28 '13 at 10:59
  • What data do you get back? if the only data is the PDF itself, no. – Zim84 Jan 28 '13 at 11:01
  • As said by other answers, you can't use this data in jQuery. This will be binary data. You need a plugin that interprets this data. You can either open a new window, use the same window, open a new frame or use an iframe to call the plugin that handels the PDF or offer the pdf as a download. Luckily a PDF plugin is common so you don't have to worry about that. – Zim84 Jan 28 '13 at 11:04
  • Well, nearly every PDF-viewer also has a plugin for browsers.. the most common is from adobe I guess. – Zim84 Jan 28 '13 at 11:11
  • @Yosep Kim Can you expain why not? – Zim84 Nov 13 '15 at 05:49
  • @Zim84 Never mind. I misunderstood. Your solution is based on getting a real PDF file and opening it in an IFRAME, right? You can in fact set the byte stream of a PDF file to SRC of the IFRAME, however, this does NOT work on IE. – Yosep Kim Nov 13 '15 at 14:25
  • @Zim88 - --You can in fact set the byte stream of a PDF file to SRC of the IFRAME--. Well, that is what I am trying without much luck, It is giving a 404 error., Any suggestions? I've seena way to save the blob to file (maybe), but I think I will get a -Local file open- error – Miguelito Dec 01 '17 at 21:10
8

Here is my way of dealing with this issue. It is based on line 50 of this pdfmake file (https://github.com/bpampuch/pdfmake/blob/master/src/browser-extensions/pdfMake.js).

  1. assuming you have a pdf stream I convert it to base64 and echo it back to my AJAX:

    $pdfString = $mpdf->Output('', 'S');
    $pdfBase64 = base64_encode($pdfString);
    echo 'data:application/pdf;base64,' . $pdfBase64;
    
  2. Here is my AJAX code. When receiving data it opens a new window and replaces url with base64 endoded data:

    var ajaxRequest = $.ajax({
        url: "php/generate-pdf/print-control.php",
        data: '',
        cache: false,
        contentType: 'application/json',
        processData: false,
        type: 'POST'
    
    });
    $.when(ajaxRequest).done(function (ajaxValue) {
        var win = window.open('', '_blank');
        win.location.href = ajaxValue;
    });
    

    The downside of this method is that you get a base64 string in the adress bar.

andrzej.szmukala
  • 942
  • 11
  • 14
  • Thanks a lot!!! After day of search this is the only answer that not display a blank pdf :) – Mistre83 Feb 05 '17 at 08:49
  • This answer should be the accepted one. It solved my problem since i always use GET for rendering PDF with html2canvas image. Since GET can't accomodate the length of the base64 encoded image, i did a rough workaround to get it work until i saw this one. :) – The Terrible Child Jul 04 '19 at 01:44
  • Thanks so much. Works well when combined with download.js like this `$.ajax({... success: function(data) {download(data, "test.pdf", "application/pdf");});` See the binary section of [download.js](http://danml.com/download.html#Download) – somesayinice Aug 16 '19 at 15:11
3

For anybody that stumbles across this. Here is an example using axios

  1. responseType must be 'arrayBuffer'
  2. create a Blob object from response
  3. create an "object url" from the blob that you can load into the iframe

        axios({
            url: `path/to/pdf`,
            method: "GET",
            responseType: 'arraybuffer'
        }).then((response) => {
            let blob = new Blob([response.data], { type: response.headers['content-type'] } );
            let url = window.URL.createObjectURL(blob);
    
            $('#frame').attr('src',url);
        });
    
Chris Rocco
  • 134
  • 1
  • 3
0

You can generate a temporary URL to access the PDF file stored on the server, instead of sending it back to the AJAX call. Just pass the generated URL back to the client. Then, when you receive the URL, you could for example do a window.location = to redirect the browser to the download.

Make sure that the correct headers are set for the generated file (Content-Disposition: attachment etc.), and all should be fine.

Edit: Although you could probably just use a regular (non-JavaScript) link to generate and download the file. But doing it via AJAX enables you to show some specific animation etc. to the user while the file is being generated.

lethal-guitar
  • 4,438
  • 1
  • 20
  • 40
  • Thanks for the quick respond. In my situation the PDF file is not physically generated on the server. And I need the AJAX call to send the input parameters to the server side. – Knissanka Jan 28 '13 at 09:51
  • Well, I see no way how to "download" a PDF file using AJAX. Either the data is processed by the browser, which can result in a download - or by JavaScript, which usually triggers DOM insertion etc. You would need a way to convert the PDF to HTML in order to display it - theoretically possible, but JavaScript is not really meant to do that, and that's probably not what you want. – lethal-guitar Jan 28 '13 at 09:54
  • Using GET parameters instead of POST is not an option? – lethal-guitar Jan 28 '13 at 09:55
  • Is there any jquery plugin which help me to do this? – Knissanka Jan 28 '13 at 10:48