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:

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


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



<!DOCTYPE html>



<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">


<script src='pdf.js'></script>


#the-canvas { border:1px solid black; } 

body {background-color: #404448;}




<canvas id="the-canvas"></canvas>



//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


    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) {