View Any PDF in WebViewer

Having extolled the virtues of Juan Antonio's base64 extension in previous posts (Create PDF, Upload any File) I set about seeing what could be done about viewing PDFs from assets and the sdcard using a similar method.

I did some hunting around on the internet and found a javascript library called PDFJS, which allowed for offline/closed system rendering of PDFs, thus no reliance on an internet connection or built-in pdf plugins in browsers. After some testing and trial and error, I have come up with a solution that allows such viewing

The workflow:

  • create a suitable html file with webviewstring capabilities
  • select a pdf file from either assets or sdcard
  • convert the pdf to a base64 string
  • modify the string for use with javascript and feed this to the webviewstring
  • view the pdf in an AI2 app

In my example there is a bit more to it than that. PDFJS can only render one page at a time, so one must have a way of changing pages, which I did by getting the number of pages from the html page once the pdf was initially rendered, then sending that value back to the app, controlling the page display from there. Also, scaling needed controlling in order to be able to zoom in and out of the pdf

BLOCKS

I will show all the blocks below but need to show the important ones that actually do the work for the display of the pdf.

First off the base64 conversion

and then the call to show the html

and now all the blocks used in the example aia project

VIDEO

anypdf.webm

HTML

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
<title>SHOWPDF</title>
<script src='pdf.js'></script>
<style> 
#the-canvas { border:1px solid black; } 
body {background-color: #404448;}
</style>
</head>
<body>
<canvas id="the-canvas"></canvas>
</body>
<script>
//gets the webviewstring and converts to a list
var wvList = window.AppInventor.getWebViewString().split(" || ");

//sets the variable with the base64 string and convert to blob
var pdfData = atob(wvList[2]);

var pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
var loadingTask = pdfjsLib.getDocument({data: pdfData});
loadingTask.promise.then(function(pdf) {

  //sets the page number from the webviewstring list
  var pageNumber = parseInt(wvList[0]);

  pdf.getPage(pageNumber).then(function(page) {

    //sets the scale value from the webviewstring list
    var scale = parseFloat(wvList[1]);

    //returns the number of pages in the pdf to the app
    window.AppInventor.setWebViewString(pdf.numPages);

    var viewport = page.getViewport({scale: scale});
    var canvas = document.getElementById('the-canvas');
    var context = canvas.getContext('2d');
    canvas.height = viewport.height;
    canvas.width = viewport.width;
    var renderContext = {
      canvasContext: context,
      viewport: viewport
    };
    var renderTask = page.render(renderContext);
    renderTask.promise.then(function () {
    });
  });
}, function (reason) {
  alert(reason);
});
</script>
</html>


CREDITS: