Displaying pdf from arraybuffer
Asked Answered
S

3

27

I am returning stream data from laravel dompdf from this code

 $pdf = \App::make('dompdf.wrapper');
 $pdf->loadHTML("<div>This is test</div>");
 return $pdf->stream();

And this is my JS ajax code

    $.ajax({
        type:"GET",
        url: "/display",
        responseType: 'arraybuffer'
    }).done(function( response ) {
        var blob = new Blob([response.data], {type: 'application/pdf'});
        var pdfurl = window.URL.createObjectURL(blob)+"#view=FitW";
        $("#pdfviewer").attr("data",pdfurl);
    });

Here is HTML to display pdf after ajax

<object id="pdfviewer" data="/files/sample.pdf" type="application/pdf" style="width:100%;height:500px;"></object>

I am getting below error

Failed to load PDF document

Please help to fix this. How to display pdf file.

Spherule answered 8/2, 2017 at 6:56 Comment(0)
T
18

jQuery.ajax() does not have a responseType setting by default. You can use a polyfill, for example jquery-ajax-blob-arraybuffer.js which implements binary data transport, or utilize fetch().

Note also, chrome, chromium have issues displaying .pdf at either <object> and <embed> elements, see Displaying PDF using object embed tag with blob URL, Embed a Blob using PDFObject. Substitute using <iframe> element for <object> element.

$(function() {

  var pdfsrc = "/display";

  var jQueryAjaxBlobArrayBuffer = "https://gist.githubusercontent.com/SaneMethod/" 
                         + "7548768/raw/ae22b1fa2e6f56ae6c87ad0d7fbae8fd511e781f/" 
                         + "jquery-ajax-blob-arraybuffer.js";

  var script = $("<script>");

  $.get(jQueryAjaxBlobArrayBuffer)
  .then(function(data) {
    script.text(data).appendTo("body")
  }, function(err) {
    console.log(err);
  })
  .then(function() {
    $.ajax({
      url: pdfsrc,
      dataType: "arraybuffer"
    })
    .then(function(data) {
      // do stuff with `data`
      console.log(data, data instanceof ArrayBuffer);
      $("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
            type: "application/pdf"
          })))
     }, function(err) {
          console.log(err);
     });

  });
});

Using fetch(), .arrayBuffer()

  var pdfsrc = "/display";

  fetch(pdfsrc)
  .then(function(response) {
    return response.arrayBuffer()
  })
  .then(function(data) {
    // do stuff with `data`
    console.log(data, data instanceof ArrayBuffer);
    $("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
        type: "application/pdf"
    })))
  }, function(err) {
      console.log(err);
  });

plnkr http://plnkr.co/edit/9R5WcsMSWQaTbgNdY3RJ?p=preview

version 1 jquery-ajax-blob-arraybuffer.js, jQuery.ajax(); version 2 fetch(), .arrayBuffer()

Taxi answered 13/2, 2017 at 1:19 Comment(5)
This is pretty good, but note that it won't let you name the PDF file.Histology
@Histology What do you mean by "name the PDF file"?Taxi
When you go to download it, you'll get the blob URL, not the name of the file.Histology
@Histology Downloading a file is not relevant to the current Question. download attribute value at <a> element only provides a suggestion for the file name at offer of file for download. The file can be renamed at Save File prompt or at local filesystem after downloading the file. See How to build PDF file from binary string returned from a web-service using javascript for question and answers relating to downloading a file.Taxi
But if you create an object or an iframe with a blob URL for the src attribute it'll have a messed up filename if you try to download it. The Q&A you link to is a pretty good solution for that (thank you!), but this answer, above, does create an issue with the name of the file if you choose to download it. Doesn't it?Histology
W
5

I like guest271314 answer a lot, especially the second version using fetch, but I wanted to add a solution that does not use a polyfill or an experimental technology like fetch.

This solution uses the native XMLHttpRequest API to create the request. This allows us to change the responseType to arrayBuffer.

  var xhr = new XMLHttpRequest();
  var pdfsrc = "https://upload.wikimedia.org/wikipedia/en/6/62/Definition_of_management.pdf";
  xhr.open('GET', pdfsrc, true);
  xhr.responseType = "arraybuffer";

  xhr.addEventListener("load", function (evt) {
    var data = evt.target.response;
    if (this.status === 200) {
      $("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data], {
        type: "application/pdf"
      })));
    }
  }, false);

  xhr.send();

I forked guest271314s plnkr to show this method in action: http://plnkr.co/edit/7tfBYQQdnih9cW98HSXX?p=preview

Wittol answered 13/2, 2017 at 13:14 Comment(0)
C
3

From my tests the responce is in response not response.data, so the following should work:

  $.ajax({
        type:"GET",
        url: "/display",
        responseType: 'arraybuffer'
    }).done(function( response ) {
        var blob = new Blob([response], {type: 'application/pdf'});
        var pdfurl = window.URL.createObjectURL(blob)+"#view=FitW";
        $("#pdfviewer").attr("data",pdfurl);
    });

Although it seems JQuery is doing something with the responce causing a blank PDF output... (PDF is blank when downloading using javascript). This will work:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'test.pdf', true);
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
   if (this.status == 200) {
        var blob=new Blob([this.response], {type:"application/pdf"});
        var pdfurl = window.URL.createObjectURL(blob)+"#view=FitW";
        $("#pdfviewer").attr("data",pdfurl);
   }
};
xhr.send();
Chainsmoke answered 10/2, 2017 at 11:53 Comment(4)
after changing response.data to response I am getting completely blank pdf. no output. I think we are near to fix this, may be need to change in responseType or Content-type any where.Spherule
@AndrewMonks "From my tests the responce is in response not response.data, so the following should work" Can you share tests at a stacksnippets, jsfiddle jsfiddle.net, or plnkr plnkr.co ?Taxi
unfortunately not as you cannot upload a pdf file to a snippet site and CORs blocks requests to other sites PDF files. Allthough see #34436633 I checked again and was getting a blank output. Try using a raw XMLHttpRequest instead of jquery and it will work.Chainsmoke
@AndrewMonks jQuery.ajax() does not have a responseType setting by default.Taxi

© 2022 - 2024 — McMap. All rights reserved.