How to embed a Base64 encoded PDF data URI into a HTML 5 `<object>` data attribute?

kibowki picture kibowki · Jul 15, 2015 · Viewed 26.8k times · Source

So in my application, users have the option to upload a file to an <input type = "file" id = "my-file"> (HTML 5 File input). I can subsequently grab this file using the following Javascript:

var files = $("#my-file").files;
var file = files[0];

Can I somehow use this var file as the data in an <object> tag? Here is an example of an object tag where the PDF is grabbed by hitting a URL and contacting the server.

<object data="data/test.pdf" /*<-- I want the var file here */ type="application/pdf" width="300" height="200">
</object>

How can I accomplish this? Please note, I must support Internet Explorer 11.

UPDATE:

I've tried something that ultimately ended in failure. I converted the PDF to a data-uri using FileReader and then used that in the data attribute of the <object> tag, which renders perfectly in Chrome but not at all in Internet explorer.

var files = $(e.currentTarget.files);
file = files[0];
var reader = new FileReader();
reader.onloadend = function() {
    var data = reader.result;
    console.log(data);
    $("#content").prepend('<object id="objPdf" data="'+data+'" type="application/pdf"></object>');
};
reader.readAsDataURL(file);

Where the reader data comes out looking like:

data:application/pdf;base64,JVBERi0xLjQKJe...

Here is the reason PDF's don't work with this approach in Internet Explorer (images only)...so sad :(

UPDATE 2:

Tried pdf.js with some success...it displays the PDF on the page, although it is incredibly slow (5 seconds for a single page) in Internet Explorer 11. It also only displays one page at a time, whereas the <object> tag displayed all pages instantly in a nice scrollable container. While this is an extreme fallback option, I'd like to not go down this route.

Anyone have any other idea as to how I can preview the PDF's that the user uploads directly in the webpage?

Answer

Dirk Schumacher picture Dirk Schumacher · Dec 15, 2016

Yes I got it working with a file...

HTML:

<object id="pdf" data="" type="application/pdf"></object>

Javascript (Jquery)

var fr = new FileReader();
fr.onload = function(evtLoaded) {
  $('#pdf').attr('data', evtLoaded.target.result );
};
fr.readAsDataURL(inFile);

Compared to your approach I use the 'I am done reading the file'-callback differently by using the event. If I got it right: 'loadend' will always be called no matter if reading succeeded or failed.