Monday, October 7, 2013

How to Generate Pdfs or Images Using Phantomjs in Codeigniter?

PhantomJS is a headless WebKit with JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG." Let's see what PhantomJS can do to fulfil my task requirements:

It renders web pages the same as the browsers which uses Webkit, such as Google Chrome or Apple Safari.
It supports SVG.
It has JavaScript API which lets me change the web page as needed.
It has a cookie API which solves the user authentication issue.
It can output the rendering page in a few formats which includes PDF.

You can easily find one helper file called "PhantomJS Wrapper Helper For CodeIgniter" in the internet which almost solves problem. Read and download it from here.

I spent almost 2 days to make this work. I followed all the steps and I was able to run it successfully via command line but not via PHP script. When I tried to generate pdfs via PHP, it didn't worked at all. I searched a lot in Google and found many suggested suggestions but none of it worked.

I then tried in the live server, it work straight away. That was very strange. :)

I knew that problem was about permission issues.

In my localhost environment, I added sudo -u anup in exec() function and it worked. :)

Don't forget to use escapeshellcmd () function as well, other wise it won't work if you have query strings in your URL.
$url = escapeshellcmd($url);
/*escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator. */

Replace the original helper file with following helper file. You can find helper file under "application/helpers/phantomjs_helper.php"
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if ( ! function_exists('rasterize_wrapper'))
 function rasterize_wrapper($url='', $output=''){
   if($url=='' || $output=='')
       show_error('URL or Output file name not defined correctly'); 
       log_message('error','rasterize_wrapper: not initialized');

        $url = escapeshellcmd($url);  // ADDED BY ME

 //using exec here, so be resposible and make sure you validate both the $output and $url above in the above function itself. I have not
 //Assuming that phantomjs's path has been included in you $PATH var

   exec('sudo -u anup phantomjs '.realpath('assets/js').'/rasterize.js '.$url.' '.realpath('assets/pdfs').$output,$output_status, $return_status); // SUDO -U USERNAME ADDED BY ME

 if($return_status=='0'){ return true;}
 return false; //something obiviously went wrong and you can check the $output and $return_status in your implementations to return more to controller.


Remember this helper file is to work around localhost only. For live server, use the exec () without any sudo
 exec('phantomjs '.realpath('assets/js').'/rasterize.js '.$url.' '.realpath('assets/pdfs').$output,$output_status, $return_status);

Don't forget to double check the files location such as rasterize.js, pdfs folder etc.

Tutorial to add PATH in terminal can be found @

Source: Generating PDFs and Thumbnails of Views.

No comments:

Post a Comment