15

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?

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
kibowki
  • 4,206
  • 16
  • 48
  • 74
  • Could just use fileReader API, wrap data in $(), strip out script tags and inject whatever is in body into a div or even put everything into iframe – charlietfl Jul 15 '15 at 21:46
  • Could you elaborate on this with some code samples? I tried the data-uri approach, using that as the source for an iframe but the iframe ended up creating an embed tag with doesn't support PDF's in Internet Explorer. – kibowki Jul 16 '15 at 20:30
  • all you need is the raw html, no need for data-uri. Set innerHTML of body with the html once iFrame loads or document.write the whole thing if it includes `` tag – charlietfl Jul 16 '15 at 20:32
  • Sorry, I think I'm missing something. Set the innerHTML of the body with what HTML? The `` tag? Just to be clear, I want to use the data in the `` with the `var file` I get from the user input, not from a file grabbed from the server. – kibowki Jul 16 '15 at 20:39
  • I might have misinterpreted the original question. I thought it was html file from title. Is this incorrect? – charlietfl Jul 16 '15 at 20:41
  • The web app is an HTML file, with an ``, which allows the user to upload a file from their filesystem. I want to grab this file (which will be a PDF), and allow them to preview it. This file they selected (`var file` from my code sample) is what I'm trying to place into the `` tag. – kibowki Jul 16 '15 at 20:45
  • might want to look at jspdf library – charlietfl Jul 16 '15 at 20:47
  • Possible duplicate of [Is there a way to generate a preview of PDF in IE](http://stackoverflow.com/questions/36461321/is-there-a-way-to-generate-a-preview-of-pdf-in-ie) – Paul Sweatte Sep 17 '16 at 20:12
  • Do you need an answer for your question now? If yes, I can give you it. – Bharata Jan 05 '19 at 08:37

2 Answers2

5

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.

Appendix on 04AUG2021:
@Adil talks about a plural of PDFs. Well, this solution talks about 1, I never tried several PDFs. Since the solution is made by an html 'id' we know that the 'id' comes with a singleton pattern per page. Nevertheless, I am convinced it is doable with severla PDFs per page somehow with whatever use case one creates.

@netotz I did not investigate here. It just comes to my mind that it could come to issues regarding the hardware. You do not mention the browser where it happens nor any operating system internals... I just guess (though I can be wrong) that 1.8 MB is rather a small amount of data...

Dirk Schumacher
  • 1,479
  • 19
  • 37
  • 2
    `` doesn't render all pdf files. I'm getting issues while rendering some particular pdfs. – Adil Dec 06 '17 at 18:18
  • I'm having issues too, particularly with sizes >1 MB, I'm not sure about the limit though, I can render a 1 MB file, but not a 1.8 MB – netotz Jul 30 '21 at 17:13
3

In addition to the above answer and the comments from Dirk's answer.(Since I don't have 50 reputation to comment directly)

I want to point out that there is a way to prevent the issue that <object> has an issue rendering base64 data directly when the file size is bigger than 1mb.

Steps:

  • Convert base64 to blob
  • Create URL from blob
  • use the URL as the data's src

A good post can be found here: an answer for another pdf lib. But this also suitable for our case.

Ash
  • 51
  • 4