Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pdf.js and viewer.js. Pass a stream or blob to the viewer

Tags:

I'm having troubles in finding a solution for this: I retrieve a PDF blob from a SQL filestream field using Javascript in this way (it's a lightswitch project)

var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" }); 

I have the blob and I can even convert it in a filestream or to base64("JVBERi0....." or "%PDF 1.6 ......", etc.)

No problem so far.

Now I need to display it in a viewer. I prefer the viewer to open in a new window but i'm open to embed it into my page somehow.

I'm wondering if I can directly pass the blob or the stream to the viewer and display the document. I've tried something like

PDFView.open(pdfAsArray, 0) 

Nothing happens in the embedded viewer in this case.

The pdfAsArray is good since I can display it appending the stream to a canvas within the same page. I just want to display the viewer, not embed the PDF in a canvas, possibly in a new window.

Can anyone provide few lines of code on how to achieve that in Javascript?

like image 297
Efrael Avatar asked Jul 02 '14 15:07

Efrael


People also ask

What is blob in pdf?

Convert PDF to Blob A Blob (or Binary Large Object) is an array of binary data.

What is pdf Viewer JS?

PDF. js is an open-source JavaScript PDF viewer that renders PDF using web standards-compliant HTML5. Primarily seen in Mozilla Firefox's as the built-in PDF viewer, PDF. js also serves as an easy way for developers and integrators to embed PDF viewing capabilities in a web app or server.


2 Answers

I'm using PDFJS.version = '1.0.1040'; PDFJS.build = '997096f';

The code that worked for me to get base64 pdf data loaded was this:

function (base64Data) {   var pdfData = base64ToUint8Array(base64Data);   PDFJS.getDocument(pdfData).then(function (pdf) {     pdf.getPage(1).then(function (page) {       var scale = 1;       var viewport = page.getViewport(scale);       var canvas = document.getElementById('myCanvas');       var context = canvas.getContext('2d');       canvas.height = viewport.height;       canvas.width = viewport.width;       page.render({ canvasContext: context, viewport: viewport });     });   });    function base64ToUint8Array(base64) {     var raw = atob(base64);     var uint8Array = new Uint8Array(raw.length);     for (var i = 0; i < raw.length; i++) {       uint8Array[i] = raw.charCodeAt(i);     }     return uint8Array;   } } 

This function could be the success function of an api call promise. What I'm doing here is rendering the pdf onto a canvas element myCanvas.

<canvas id="myCanvas"></canvas> 

This shows the first page of the pdf but has no functionality. I can see why the viewer is desirable. If I get this hooked up to the viewer (viewer.html / viewer.js) I will edit my answer.

EDIT: How to hook up the viewer

1 In bower.json, add "pdfjs-viewer": "1.0.1040"

2 Html:

<iframe id="pdfViewer" src="lib/pdfjs-viewer/web/viewer.html" style="width: 100%; height: 700px;" allowfullscreen="" webkitallowfullscreen=""></iframe> 

3 Change the stupid default document in the viewer.js file:

var DEFAULT_URL = '';

4 Controller:

var pdfjsframe = document.getElementById('pdfViewer'); pdfjsframe.onload = function() {   LoadPdfDocument(); };  $scope.myApiCallThatReturnsBase64PdfData.then(   function(base64Data) {     $scope.base64Data = base64Data;     LoadPdfDocument();   },   function(failure) {      //NotificationService.error(failure.Message);    });  function LoadPdfDocument() {   if ($scope.PdfDocumentLoaded)     return;   if (!$scope.base64Data)     return;    var pdfData = base64ToUint8Array($scope.base64Data);   pdfjsframe.contentWindow.PDFViewerApplication.open(pdfData);    $scope.PdfDocumentLoaded = true; }  function base64ToUint8Array(base64) {   var raw = atob(base64);   var uint8Array = new Uint8Array(raw.length);   for (var i = 0; i < raw.length; i++) {     uint8Array[i] = raw.charCodeAt(i);   }   return uint8Array; } 
like image 62
toddmo Avatar answered Sep 24 '22 06:09

toddmo


If you've got an typed array (e.g. an Uint8Array), then the file can be opened using PDFView.open(typedarray, 0);.

If you've got a Blob or File object, then the data has to be converted to a typed array before you can view it:

var fr = new FileReader(); fr.onload = function() {     var arraybuffer = this.result;     var uint8array = new Uint8Array(arraybuffer);     PDFView.open(uint8array, 0); };    fr.readAsArrayBuffer(blob); 

Another method is to create a URL for the Blob/File object:

var url = URL.createObjectURL(blob); PDFView.open(url, 0); 

If the PDF Viewer is hosted at the same origin as your website that embeds the frame, then you can also view the PDF by passing the blob URL to the viewer:

var url = URL.createObjectURL(blob); var viewerUrl = 'web/viewer.html?file=' + encodeURIComponent(url); // TODO: Load the PDF.js viewer in a frame or new tab/window. 
like image 41
Rob W Avatar answered Sep 24 '22 06:09

Rob W