Search code examples
javascriptpdfpdf.jspdf-viewer

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


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?


Solution

  • I finally made the PDFView.open method working. Now if I embed the viewer into my page and call the open function as Rob suggested in the first 2 examples it works.

    For those who are looking for this kind of solution I provide some lines of code here:

    This is the code in my Lightswitch mainPage.lsml.js. The js scripts (pdf.js, viewer and Others) are referenced in the main html page of the Lightswitch project (Default.html); I assume it should work with any other html page not Lightswitch based.

    myapp.MainPage.ShowPdf_execute = function (screen) {
    // Write code here.
    // Getting the stream from sql
    var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });
    // Pass the stream to an aspx page that makes some manipulations and returns a response
    var formData = new FormData();
    formData.tagName = pdfName;
    formData.append(pdfName, blob);
    var xhr = new XMLHttpRequest();
    var url = "../OpenPdf.aspx";
    xhr.open('POST', url, false);
    xhr.onload = function (e) {
        var response = e.target.response;
            var pdfAsArray = convertDataURIToBinary("data:application/pdf;base64, " + response);
            var pdfDocument;
    // Use PDFJS to render a pdfDocument from pdf array
        PDFJS.getDocument(pdfAsArray).then(function (pdf) {
            pdfDocument = pdf;
            var url = URL.createObjectURL(blob);
            PDFView.load(pdfDocument, 1.5)
        })
    };
    xhr.send(formData);  // multipart/form-data 
    };
    

    This is the convertDataURIToBinary function

    function convertDataURIToBinary(dataURI) {
    var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
    var base64 = dataURI.substring(base64Index);
    var raw = window.atob(base64);
    var rawLength = raw.length;
    var array = new Uint8Array(new ArrayBuffer(rawLength));
    
    for (i = 0; i < rawLength; i++) {
        array[i] = raw.charCodeAt(i);
    }
    return array;
    }
    

    What is still missed is the possibility to pass the stream directly to the viewer.html page in order to open it in a new window and have a separate ui where make the rendering.

    This code is still not working since I got an empty viewer with no document inside:

    var blob = new Blob([screen.WebReportsPdfFilesStream.selectedItem.Pdf], { type: "application/pdf;base64" });
    var url = URL.createObjectURL(blob);
    var viewerUrl = 'Scripts/pdfViewer/web/viewer.html?file=' + encodeURIComponent(url);
    window.open(viewerUrl);
    

    Looks like the encodeURIComponent(url) is not passing to the viewer a good object to load into the viewer. Any idea or suggestion?