4

There is a 3rd party service which sends me a PDF file in either binary string or base64 encoded. Is there any possibility to display the PDF embedded in IE 11 using either binary string or base64 encoded.

From SO and other forums, I concluded that IE 11 supports data uri only for images and not PDF (I might be wrong) which rules out base64. So the only option left is to display from binary string. I am using it in a Node App but I do not have the option to first save the retrieved file to Node server and use static URL.

Please let me know if above is achievable in IE 11.

Currently I'm trying to use npm package of https://github.com/pipwerks/PDFObject. For Chrome & Firefox, I retrieve the base64 file and embed it using the above package and works fine.

roray
  • 756
  • 1
  • 16
  • 35
  • Did you ever find a solution? – John Doe Dec 15 '16 at 16:52
  • @JDS please refer to my answer. – roray Dec 19 '16 at 04:06
  • Possible duplicate of [Saving Base64 encoded PDF with Internet Explorer 10 and below](http://stackoverflow.com/questions/27154606/saving-base64-encoded-pdf-with-internet-explorer-10-and-below) – SanjiMika Apr 19 '17 at 16:54
  • @QuangMinhLENGUYEN yes my friend. However, that answer din't exist 4 months ago before you posted the answer today on the duplicate question that you mentioned. Although, do note your answer still does not display the embedded PDF in IE as was the original ask of this question – roray Apr 20 '17 at 19:48
  • @roray with my solution, when clicking button "Downloading", the browser ask you to open or download the PDF file from base64 string. The code line which allow that is : window.navigator.msSaveOrOpenBlob(blob, fileName); You could test my code from jsfiddle in your IE browser by changing data variable : PDF file base64 string. – SanjiMika Apr 26 '17 at 08:17
  • Beside, you could see the test result in my IE browser : https://drive.google.com/open?id=0B7rMn0jKIMCnbUZfbFk1UXVHUkU – SanjiMika Apr 26 '17 at 08:37
  • @QuangMinhLENGUYEN can you share a screenshot of embedded pdf display in IE11. The screenshot in your comment is for downloading the PDF – roray Apr 26 '17 at 17:47

2 Answers2

4

This solution uses [pdf.js] 1

Key steps in rendering a base64 PDF using PDF.js library

  • First decode it using atob
  • Then initializing a Uint8Array using above decoded data

Abstract from express-pdfjs/scripts/App.js

let options = {
      method: 'GET',
      uri: 'http://localhost:5000/getBase64Pdf',
      resolveWithFullResponse: true
    }
rp(options)
  .then((response) => {
    if (response.statusCode !== 200) {
      console.error('http not 200 but : ', response.statusCode)
    } else {
      console.info('connected successfully : ' + response.statusCode)
      let pdfData = atob(response.body)
      let uint8ArrayPdf = new Uint8Array(pdfData.length)
      for (let i = 0; i < pdfData.length; i++) {
        uint8ArrayPdf[i] = pdfData.charCodeAt(i)
      }
      let pdfjsframe = document.getElementById('pdfViewer');
      pdfjsframe.contentWindow.PDFViewerApplication.open(uint8ArrayPdf);
    }
  })

pdfViewer is an iframe in index.html

<iframe id="pdfViewer" src="http://localhost:3000/express-pdfjs/pdfViewer/web/viewer.html" height="1600" width="850" />

Please find a sample implementation for this using React on client side @ https://github.com/rohanray/so-pdf-base64

roray
  • 756
  • 1
  • 16
  • 35
  • Does this method (....PDFViewerApplication.open(uint8ArrayPdf) ) work (is supported) in IE 11/Edge? – user3590235 Oct 05 '18 at 16:37
  • @user3590235 It definitely works in IE 11 as this solution was required specifically for IE 11. You can try. I don't have a Windows machine at this point to test in IE 11 – roray Oct 06 '18 at 06:22
  • Thanks @roray. I actually went ahead and tried. It works and both on IE 11 and Edge but its toooo slow i'm trying to find a way to resolve that. – user3590235 Oct 06 '18 at 16:17
  • 1
    @user3590235 Array operations can be CPU intensive. What's the approximate size of the document? You can try running above array operations on service worker. – roray Oct 08 '18 at 03:07
  • @roray thank you so much for the tip. Its a Fed. Holiday today so don't have access to the doc today but obviously its big enough to cause the issue (in IE - Chrome dose it fast). I will use a [Service Worker](https://googlechrome.github.io/samples/service-worker/basic/) when I get to office tomorrow. – user3590235 Oct 08 '18 at 13:19
  • @user3590235 by the way, there is no native implementation of service workers in IE 11, so will have to be some polyfill ... plz update here how it goes :) – roray Oct 11 '18 at 11:46
  • @roray I used [web worker](https://caniuse.com/#feat=webworkers) instead - the array from worker returns fast but pdf loading on viewer.html still slow. I found [some reasoning](https://github.com/mozilla/pdf.js/issues/8887#issuecomment-328201178) here. Bottom line: found another way to use viewer.html with MS Edge (fast like FF/Ch) but IE 11 remains hopeless for me so I used var blob = new Blob([this.response], {type: 'application/pdf' });window.navigator.msSaveOrOpenBlob(blob, fileName);. I will add my solution as an answer plz let me know if you find a way to improve IE 11 performance. – user3590235 Oct 12 '18 at 15:18
1

Following the discussion with @roray - I'm adding a slightly different solution on the menu here :) First off: 1.not using base64 string for this (although possible). 2. I'm working on asp mvc 3. using viewer.html viewer of pdf.js

So, from the server/controller fetch file from db and return bites

public ActionResult LoadFile(int id)
{
   var file = db.Files.Where(i => i.Id == id).FirstOrDefault();
   return File(file.BinaryFile, MediaTypeNames.Application.Pdf, "Name.pdf");
}

In the view/html add an iframe with source unspecified (src="") alternatively can created it on the fly on page-load event.BTW, I tried object, embed and iframe with FF/Chrome/Edge/IE 11 and found iframe seems to work consistently across the board. Dont like iframe though :/

<iframe src="" name="printDoc" id="printDoc" width="800" height="1000" type="application/pdf"></iframe>

Finally, in your script tag. This can be done via Ajax just the same. Basically, soon as the document is ready call the server, get the file in bytes, convert to blob url, append the blob url to the relative location of '/web/viewer.html?file=' in your project and update the src="" attribute of your iframe.

 $(document).ready(function myfunction() {
 var xhr = new XMLHttpRequest();
    // works for EDGE/Chrome/FFox
    xhr.open("GET", "/Documents/LoadFile/" + fileId, true);
    xhr.responseType = "blob";
    xhr.onload = function (e) {
        if (this.status === 200) {
            var blob = new Blob([this.response], { type: 'application/pdf' });
            console.log('Not IE 11');
            var url = window.URL.createObjectURL(blob);
            _iFrame = document.querySelector("#printDoc");
            _iFrame.setAttribute('src', '/web/viewer.html?file=' + url);
        }
    };
    xhr.send();
    
});

This will open the pdf embedded in the viewer.html embedded in the iframe. MS Edge works fine with this but not the blob url being sent as a query param over the address bar which obviously is supported by FF/Chrome. And, that's why I took this option.

PS. IE 11 remains hopeless for me so I used var blob = new Blob([this.response], {type: 'application/pdf' });window.navigator.msSaveOrOpenBlob(blob, fileName);Please let me know if you find a way to improve IE 11 performance

user3590235
  • 153
  • 7