PHP PDF Viewer - Convert to Images and use HTML/JS

This post is more than 18 months old. Since technology changes to rapidly, this content may be out of date (but that's not always the case). Please remember to verify any technical or programming information with the current release.

Well - I really couldn’t think of a good title - it’s really not catchy at all.

Anyway… at my last job, we were contemplating making a PDF reading solution that would easily scale, work on multiple devices, and allow advertisements along side of them. I left before we began this project, but it hasn’t ever left my mind.

I decided to do a quick proof of concept. Turns out Imagick with PHP will convert PDF to jpeg really quick and easy. So, I wrote the following PHP class to work with this.

namespace AaronSaray;

class PDFViewer
{
  /**
   * @const string the location of the PDF files in relation to this class
   */
  const PDF_DIR = '/pdf';

  /**
   * @const string the cache location
   */
  const CACHE_DIR = '/pdf/cache';

  /**
   * Get the PDF files
   * @return array
   */
  public function getPDFList()
  {
    return glob(__DIR__ . self::PDF_DIR . '/*.pdf');
  }

  /**
   * Creates an image list by either processing the pdf or 
   * retrieving them from the cache
   *
   * @param $filename
   * @return array
   * @throws \Exception
   */
  public function getImageList($filename)
  {
    $filePath = __DIR__ . self::PDF_DIR . "/{$filename}";
    if (!is_readable($filePath)) {
      throw new \Exception($filePath . ' was not readable.');
    }

    $dirName = substr(basename($filePath), 0, -4);
    $cacheLocation = __DIR__ . self::CACHE_DIR . "/{$dirName}";
    $globPattern = $cacheLocation . '/*.jpg';

    $files = glob($globPattern);
    if (empty($files)) {
      $this->processFileToImageCache($filePath, $cacheLocation);
      $files = glob($globPattern);
    }

    return $files;
  }

  /**
   * Write a rendered PDF to the cache.
   *
   * @param $filePath
   * @param $cacheLocation
   */
  protected function processFileToImageCache($filePath, $cacheLocation)
  {
    if (!is_dir($cacheLocation)) mkdir($cacheLocation);

    $imagick = new \Imagick();
    $imagick->setResolution(150,150);
    $imagick->readImage($filePath);
    $imagick->writeImages($cacheLocation . '/rendered.jpg', true);
  }
}

Simply put, you’ll call one function to get a list of PDFs - and then you can feed a PDF to the other function to make it write it to the cache - or read it from the cache.

Finally, add in a little jQuery:

$(function() {
  $('#pdf img:first-child').show();
  $('#pdf').on('click', function() {
    var visibleImage = $('img:visible', $(this));
    var nextImage = visibleImage.next();
    if (nextImage.length == 0) {
      nextImage = $(visibleImage.siblings()[0]);
    }
    visibleImage.fadeOut();
    nextImage.fadeIn();
  })
});

This simply will skip through the images one by one on click - and restart from the beginning. Not particularly pretty, but it’s just a proof of concept.

Check out the demo here.

Return to All Posts