For an app I’m working on, we need a new feature: to show some pdf stored server side.

After some research I found three different solutions to explore:

  1. using a Cordova plugin like Reader
  2. trying with the promising PDF.js, a solution completely based on js to parse/render PDFs client side.
  3. parse PDF on server side, render it as images and let the client manage an easy jpg.

Using Cordova / native code

This is of course the cleaner solution and probably the less error-prone one, but as I’m using Intel XDK (because afaik it’s the only solution to develop iOS application with Linux) and you can’t debug Cordova plugin in real-time with it, it’s a pain to upload and build the app everytime before trying to play with it, we are not in ninethees anymore when compile time was normal.

PDF.js

The first time I looked at this, I thought that this would be the solution I was going to choose. The Mozilla team has done a great job here and is stable enougth that they included the reader in Firefox, as you can see using a recent release of Firefox and watching the demo and the pdf used for the demo alone (the interface it’s the same and the console shows same logs).

The only issue with PDF.js is speed, as with the big PDFs I’m going to work with, the smoothness of application it’s a bit downgraded.

Choosed solution / server side conversion

There are lot of solutions to convert PDF into images and also some script to convert a PDF directly into HTML. My solution is splitted into:

Convert PDF into images:

#! /bin/bash
# Mass convert PDF to png - massPDF2PNG.sh
# settings
PDF_PATH=pdf
PNG_PATH=images
# check if destination path exists
if [ ! -d $PNG_PATH ]; then
mkdir $PNG_PATH
fi
# convert command / install ImageMagick to use this
convert="convert -density 300 "
# for each pdf found on selected path
for pdf in `ls $PDF_PATH/*.pdf`; do
name=$(basename $pdf .pdf)
# check if this pdf is converted yet
ls $PNG_PATH/$name*.png 2> /dev/null > /dev/null
if [ $? -eq 0 ]; then
echo "$pdf converted yet! "
else
# convert it and put in destination path
$convert $pdf $PNG_PATH/$name.png
if [ $? -ne 0 ]; then
echo "Error converting $pdf"
exit 1
fi
fi
done
exit 0

This script has to be executed server-side for each changes on pdf directory!

To achieve this in linux we can use inotify, using a little stackoverflow script.

#! /bin/bash
# notify_changes.sh
DIRECTORY_TO_OBSERVE="pdf"
function block_for_change {
inotifywait \
-e modify,move,create,delete \
$DIRECTORY_TO_OBSERVE
}
BUILD_SCRIPT=massPDF2PNG.sh
function build {
bash $BUILD_SCRIPT
}
build
while block_for_change; do
build
done

So after installing inotify-tools we can run ./notify_changes.sh and start copy PDFs into pdf/ directory. Converting PDFs into images is slow but after a while you’ll found your images (one per page) inside proper directory.

Last thing, we need to prepare an HTML page to host our images and put some pretty css to “emulate” a book style pages:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
<style type="text/css" media="all">
html, body {
margin: 0;
padding: 0;
border: 0;
background-color: #9E9E9E;
}
img {
background-color: #fff;
box-sizing: border-box;
display: block;
border: 2px solid #444;
width: 100%;
margin: 0 0 5px 0;
}
</style>
</head>
<body>
<img class="" alt="" src="compressed.tracemonkey-pldi-09-0.png"/>
<img class="" alt="" src="compressed.tracemonkey-pldi-09-1.png"/>
<img class="" alt="" src="compressed.tracemonkey-pldi-09-2.png"/>
<img class="" alt="" src="compressed.tracemonkey-pldi-09-3.png"/>
</body>
</html>

And here a little demo!

dev, app, pdf