Properly Create and Serve PDF Blob via HTML5 File and URL APIs
Asked Answered
S

3

31

Ok, Let's say I have document data stored somewhere, let's arbitrarily take this pdf.

Issue #1. What I want to do is make an AJAX call to this URL (because I need to pass some authentication headers and it is cross domain). Then take the returned data, create a blob url for it, append an iFrame to the DOM, and direct the src to the blob url.

Currently my code looks like this:

$.ajax({
  url:'http://www.grida.no/climate/ipcc_tar/wg1/pdf/tar-01.pdf'
}).done(function(data){
   var file = new Blob([data], {type:'application/pdf'}),
       url = URL.createObjectURL(file),
       _iFrame = document.createElement('iframe');
      _iFrame.setAttribute('src', url);
      _iFrame.setAttribute('style', 'visibility:hidden;');
      $('#someDiv').append(_iFrame);
});

Unfortunately, I am getting a 'Failed to Render PDF' in the iFrame.

Issue #2. I'd like this to result in a file download prompt. Not sure how to guarantee this given that PDF's will naturally just display in the iFrame.

Schneider answered 17/3, 2013 at 23:53 Comment(2)
the data string begins like this: %PDF-1.5 %���� 2504 0 obj <</Linearized 1/L 3722399/O 2506/E 388168/N 36/T 3720768/H [ 462 773]>> endobj 2511 0 obj <</DecodeParms<</Columns 3/Predictor 12>>/Filter/FlateDecode/ID[<F9EFEA8C46FA46DBA17E65AF85B66228><EF984B2A947E994D999C77E6D2021030>]/Index[2504 10]/Info 2503 0 R/Length 47/Prev 3720769/Root 2505 0 R/Size 2514/Type/XRef/W[1 2 0]>>stream h�bbdb9�����]�x?abP|...Schneider
Just FYI to anyone. Ended up completely working around this issue because it didn't seem possible. I ended up serving the files temporarily for 10s, pointing an iframe to its arbitrary url, and removing them after download (no authentication other than browser cookies).Schneider
H
43

jQuery.ajax does not currently support blobs, see this bug report #7248 which is closed as wontfix.

However it's easy to do XHR for blobs without jQuery:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.grida.no/climate/ipcc_tar/wg1/pdf/tar-01.pdf', true);
xhr.responseType = 'blob';

xhr.onload = function(e) {
  if (this.status == 200) {
    // Note: .response instead of .responseText
    var blob = new Blob([this.response], {type: 'application/pdf'}),
        url = URL.createObjectURL(blob),
        _iFrame = document.createElement('iframe');

    _iFrame.setAttribute('src', url);
    _iFrame.setAttribute('style', 'visibility:hidden;');
    $('#someDiv').append(_iFrame)        
  }
};

xhr.send();

Shamelessly copied from HTML5rocks.

If jQuery did support the Blob type, it could be as simple as:

$.ajax({
  url:'http://www.grida.no/climate/ipcc_tar/wg1/pdf/tar-01.pdf',
  dataType:'blob'
})...
Harrod answered 23/5, 2013 at 10:42 Comment(4)
Thank you, it works. But what if I don't know the type 'application/pdf' in prior? Can I use the MIME type from the response?Latonia
Yes, you can use mimetype from the response. Note however, that this solution will not allow you to name the file that people end up downloading. It'll always be some nasty hash or something.Limoges
can anyone suggest how to show pdf without third party API.. using XMLhttpReuqest or filereader. when we are selecting pdf file from fileupload control in htmlProstomium
How much can be the maximum size of the file we can create using blob on a browser tab?Dode
K
1

I have used @Ciantic answer to adapt my answer. I have avoided using iframe obj and the user can download the file directly from the page.

var link = 'http://www.grida.no/climate/ipcc_tar/wg1/pdf/tar-01.pdf';
$("body").addClass("loading"); // adding the loading spinner class

var xhr = new XMLHttpRequest();
xhr.open('GET',link,true);
xhr.responseType = 'blob';

        xhr.onload = function(e){
                 if (this.status == 200) {
                    var a = document.createElement('a');
                    var url = window.URL.createObjectURL(new Blob([this.response], {type: 'application/pdf'}));
                    a.href = url;
                    a.download = 'report.pdf';
                    a.click();
                    window.URL.revokeObjectURL(url);
                    $('body').removeClass("loading"); //removing the loading spinner class
                  }else{
                      $('body').removeClass("loading") //removing the loading spinner class
                      console.log(this.status);
                      alert('Download failed...!  Please Try again!!!');
                  }
            };
            xhr.send();
Kind answered 7/2, 2019 at 8:46 Comment(0)
S
1
var src_url = your url here;
var contentDisposition = 'AlwaysInline';
var src_new = src_url.replace(/(ContentDisposition=).*?(&)/, '$1' + contentDisposition + '$2');

By doing this you will be able to view pdf instead of downloading it,

Header ContentDisposition should be 'AlwaysInline' then only it displays your file instead of downloading it.

Shayn answered 16/5, 2019 at 11:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.