The best HTML to PDF library for PHP?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

The best HTML to PDF library for PHP?

Post by Christopher »

Does anyone have a HTML to PDF solution that they are happy with? It could be a PHP library or a command line program.
(#10850)
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: The best HTML to PDF library for PHP?

Post by Benjamin »

I'm sure I'll need to do this at one point or another so I did some research on the hunch that I could use openoffice via the command line to automate the process.

I found this page which I believe includes everything required in order to do so.

Here is another solution which uses HTML2PDF, an open source project on sourceforge.
User avatar
Darhazer
DevNet Resident
Posts: 1011
Joined: Thu May 14, 2009 3:00 pm
Location: HellCity, Bulgaria

Re: The best HTML to PDF library for PHP?

Post by Darhazer »

We are using HTML2PDF, however we have problems with page breaks (sometimes last line of the page appears only the half of it)

Another approach we are currently researching (but this if you have a template with fixed amount of data, i.e. you have no multiple rows with varying count to insert, but only single variables) is making a PDF with markers in it, and than with PHP just enter the data in those markers.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: The best HTML to PDF library for PHP?

Post by Christopher »

Darhazer wrote:We are using HTML2PDF, however we have problems with page breaks (sometimes last line of the page appears only the half of it)
I tried it, but they only seem to give example HTML files and not much example PHP code. I used the example on some simple files but it does not produce a valid PDF file. Hmmmm....
Darhazer wrote:Another approach we are currently researching (but this if you have a template with fixed amount of data, i.e. you have no multiple rows with varying count to insert, but only single variables) is making a PDF with markers in it, and than with PHP just enter the data in those markers.
Does this work? If it does it would probably be the easiest way. How do you find the markers/tags in the PDF file?
(#10850)
User avatar
Darhazer
DevNet Resident
Posts: 1011
Joined: Thu May 14, 2009 3:00 pm
Location: HellCity, Bulgaria

Re: The best HTML to PDF library for PHP?

Post by Darhazer »

We are still researching, the libraries are:
fpd
setasign

As for the html2pdf, here is example code:

Code: Select all

 
// Util
require_once(dirname(__FILE__) . '/../../html2pdf-2.1.5/config.inc.php');
    require_once(HTML2PS_DIR . 'pipeline.factory.class.php');
    require_once(HTML2PS_DIR . 'fetcher.url.class.php');
    
    class fclHtml2Pdf {
        protected $_html;
        
        function fclHtml2Pdf()
        {
            $this->_init();
            parse_config_file(HTML2PS_DIR . 'html2ps.config');
        }
        
        function _init()
        {
            global $g_config;
            
            $g_config = array(
                'cssmedia'      => 'screen',
                'convert'       => 1,
                'media'         => 'A4',
                'scalepoints'   => 1,
                'renderimages'  => 1,
                'renderlinks'   => 1,
                'pagewidth'     => 800,
                'landscape'     => 0,
                'method'        => 'fpdf',
                'margins'       => array( 'left' => 30, 'right' => 30, 'top' => 15, 'bottom' => 15),
                'encoding'      => 'utf-8',
                'compress'      => 1,
                'output'        => 1,
                'pdfversion'    => '1.5',
                'transparency_workaround' => 0,
                'imagequality_workaround' => 0,
                'draw_page_border' => 0,
                'debugbox'      => 0,
                'html2xhtml'    => 1,
                
                'debugnoclip'   => false,
            );
        }
        
        function setHtml($html)
        {
            $this->_html = $html;
        }
        
        function setFilename($filename)
        {
            global $g_baseurl;
            $g_baseurl = $filename;
        }
        
        function setTitle($title)
        {
            $this->_title = $title;
        }
        
        function generate()
        {
            global $g_config,
            $g_border,
            $g_font_size,
            $g_table_border,
            $g_baseurl,
            $g_css_index,
            $g_font_weight,
            $g_font_style,
            $g_font_family,
            $g_image_encoder,
            $g_stylesheet_title,
            $g_media,
            $g_framepos,
            $g_px_scale,
            $g_pt_scale;
                        
            // begin processing
            $g_media = Media::predefined($g_config['media']);
            $g_media->set_landscape($g_config['landscape']);
            $g_media->set_margins($g_config['margins']);
            $g_media->set_pixels($g_config['pagewidth']);
            
            // Initialize the coversion pipeline
            $pipeline = new Pipeline();
            
            // Configure the fetchers
            $pipeline->fetchers[] = new miFetcher($this->_html);
            //$pipeline->fetchers[] = new FetcherURL();
            
            // Configure the data filters
            $pipeline->data_filters[] = new DataFilterDoctype();
            $pipeline->data_filters[] = new DataFilterUTF8($g_config['encoding']);
            if ($g_config['html2xhtml']) {
              $pipeline->data_filters[] = new DataFilterHTML2XHTML();
            } else {
              $pipeline->data_filters[] = new DataFilterXHTML2XHTML();
            };
            
            $pipeline->parser = new ParserXHTML();
 
            // "PRE" tree filters
 
            $pipeline->pre_tree_filters = array();
            
            $header_html    = '';
            $footer_html    = '';
            $pipeline->pre_tree_filters[] = new PreTreeFilterHeaderFooter($header_html, $footer_html);
            
            if (isset($g_config['renderfields'])) {
              $pipeline->pre_tree_filters[] = new PreTreeFilterHTML2PSFields();
            };
            
            // 
            
            if ($g_config['method'] === 'ps') {
              $pipeline->layout_engine = new LayoutEnginePS();
            } else {
              $pipeline->layout_engine = new LayoutEngineDefault();
            };
            
            $pipeline->post_tree_filters = array();
            
            // Configure the output format
            if (@$g_config['pslevel'] == 3) {
              $image_encoder = new PSL3ImageEncoderStream();
            } else {
              $image_encoder = new PSL2ImageEncoderStream();
            };
            
            switch ($g_config['method']) {
             case 'fastps':
               if ($g_config['pslevel'] == 3) {
                 $pipeline->output_driver = new OutputDriverFastPS($image_encoder);
               } else {
                 $pipeline->output_driver = new OutputDriverFastPSLevel2($image_encoder);
               };
               break;
             case 'pdflib':
               $pipeline->output_driver = new OutputDriverPDFLIB16($g_config['pdfversion']);
               break;
             case 'fpdf':
               $pipeline->output_driver = new OutputDriverFPDF();
               break;
             case 'png':
               $pipeline->output_driver = new OutputDriverPNG();
               break;
             case 'pcl':
               $pipeline->output_driver = new OutputDriverPCL();
               break;
             default:
               die("Unknown output method");
            };
            
            $pipeline->output_driver->setTitle($this->_title);
            $pipeline->output_driver->setAuthor('Mirchev Ideas Ltd.');
            
            // Setup watermark
            $watermark_text = '';
            $pipeline->output_driver->set_watermark($watermark_text);
            if ($g_config['debugbox']) {
              $pipeline->output_driver->set_debug_boxes(true);
            }
            
            if ($g_config['draw_page_border']) {
              $pipeline->output_driver->set_show_page_border(true);
            } 
              
            if (@$g_config['ps2pdf']) {
              $pipeline->output_filters[] = new OutputFilterPS2PDF($g_config['pdfversion']);
            }
            
            if ($g_config['compress'] && $g_config['method'] == 'fastps') {
              $pipeline->output_filters[] = new OutputFilterGZip();
            }
            
            $filename = $g_baseurl;
            switch ($g_config['output']) {
             case 0:
               $pipeline->destination = new DestinationBrowser($filename);
               break;
             case 1:
               $pipeline->destination = new DestinationDownload($filename);
               break;
             case 2:
               $pipeline->destination = new DestinationFile($filename);
               break;
            };
            
            // Start the conversion
            $status = $pipeline->process($g_baseurl, $g_media);
            
            if ($status == null) {
              print($pipeline->error_message());
              error_log("Error in conversion pipeline");
              die();
            }
            
        }
    }
    
    class miFetcher extends FetcherUrl {
        public function __construct($html)
        {
            $this->_html = $html;
            parent::__construct();
        }
        
        public function get_data($data_id)
        {
            // If it is NOT a URL use the FetchedDataURL - this is the html of the report
            if ((strlen($data_id) < 7) or substr_compare($data_id, 'http://', 0, 7))
                return new FetchedDataURL($this->_html, array(), "");
            
            $data = parent::get_data($data_id);
            
            return $data;
        }
        
        public function get_base_url()
        {
            return 'http://' . $_SERVER['HTTP_HOST'] . '/';
        }
    }
 

Code: Select all

 
// actual code
class fclPdfExportAction extends miActionWithWebForm {
        
        protected $_title = '';
        protected $_filename = '';
            
        /**
         * Generates the HTML from the template
         * Subclasses can override to provide custom logic for parsing the template
         */
        protected function generateHtml($template)
        {
                // enter some html, framewok-secific code removed           
                 return $html;
        }
            
        public function doAction()
        {
            $html = $this->generateHtml($this->_view->getTemplateFileName($this->template));
            
            $pdf = &new fclHtml2Pdf();
            $pdf->setHtml($html);
            $pdf->setFilename($this->_filename);
            $pdf->setTitle($this->_title);
            $pdf->generate();
            exit;
        }   
    }
User avatar
jazz090
Forum Contributor
Posts: 176
Joined: Sun Apr 12, 2009 3:29 pm
Location: England

Re: The best HTML to PDF library for PHP?

Post by jazz090 »

php pdfing can be a real pain in the ass, i was exhausted after 1 month and what i accomplished on my own sever failed to show up on my business plan. there are cheap ways and expensive ways of doing it in my experience. the best on is openoffice as mentioned but there are some cheap alternatives if you cant afford a VPS that can be brought to attention by google.
User avatar
Eran
DevNet Master
Posts: 3549
Joined: Fri Jan 18, 2008 12:36 am
Location: Israel, ME

Re: The best HTML to PDF library for PHP?

Post by Eran »

Did you try Zend_Pdf?
User avatar
jazz090
Forum Contributor
Posts: 176
Joined: Sun Apr 12, 2009 3:29 pm
Location: England

Re: The best HTML to PDF library for PHP?

Post by jazz090 »

pytrin wrote:Did you try Zend_Pdf?
ohh threes that as well, i have teared this framework upside down and it still needs a lot of work as its lacking some important features. see the problem is all PHP-PDF frameworks available right now only make PDF from scratch which hardly comes in handy. most of developers want to convert from existing .doc, .docx, .rtf and .wp files.
User avatar
flying_circus
Forum Regular
Posts: 732
Joined: Wed Mar 05, 2008 10:23 pm
Location: Sunriver, OR

Re: The best HTML to PDF library for PHP?

Post by flying_circus »

arborint wrote:
Darhazer wrote:Another approach we are currently researching (but this if you have a template with fixed amount of data, i.e. you have no multiple rows with varying count to insert, but only single variables) is making a PDF with markers in it, and than with PHP just enter the data in those markers.
Does this work? If it does it would probably be the easiest way. How do you find the markers/tags in the PDF file?
I've got some experience working with PDF's.

I'm not sure I understand exactly what you are trying to accomplish, but we use it to populate PDF order form. I've built a flash interface for the user to select their options, and then a print button which creates a POST to the generate PDF page. That generate PDF page parses the POST information and inserts the data into the PDF form. It's called FDF data fields. I use acrobat pro to make forms fields in the PDF.

The other program I use is PDFlib. PDFlib can import an existing .pdf file and basically rasterize it as a background. Then you can super-impose your data over top of the background drawing by x and y coords.

I can probably send a few snippets of code if you are interested in either method.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: The best HTML to PDF library for PHP?

Post by Christopher »

Darhazer wrote:We are still researching, the libraries are:
fpd
setasign

As for the html2pdf, here is example code:
Thanks for the links and code. I will need to dig through your classes to see what you are doing ... and get rid of the pipline stuff which I don't need. I just need to convert one at a time -- on demand.
(#10850)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: The best HTML to PDF library for PHP?

Post by Christopher »

pytrin wrote:Did you try Zend_Pdf?
I think Zend_Pdf like many others only generates PDFs programmatically. I am looking for HTML to PDF conversion. I may end up having to do the PDFs in code.
(#10850)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: The best HTML to PDF library for PHP?

Post by Christopher »

flying_circus wrote:I've got some experience working with PDF's.

I'm not sure I understand exactly what you are trying to accomplish, but we use it to populate PDF order form. I've built a flash interface for the user to select their options, and then a print button which creates a POST to the generate PDF page. That generate PDF page parses the POST information and inserts the data into the PDF form. It's called FDF data fields. I use acrobat pro to make forms fields in the PDF.

The other program I use is PDFlib. PDFlib can import an existing .pdf file and basically rasterize it as a background. Then you can super-impose your data over top of the background drawing by x and y coords.

I can probably send a few snippets of code if you are interested in either method.
Thanks for the tips, and any code you can post would be welcome. I have what is essentially a receipt that is currently HTML. I need to make it also available as PDF. If I can convert the existing one on-the-fly that would be easiest, and I would not have to support two versions of each receipt type (there are 20-30) because changes to a HTML one would automatically be reflected in the PDFs.
(#10850)
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Re: The best HTML to PDF library for PHP?

Post by Benjamin »

You could always just create a gif of the receipt and throw it into a PDF document.
User avatar
flying_circus
Forum Regular
Posts: 732
Joined: Wed Mar 05, 2008 10:23 pm
Location: Sunriver, OR

Re: The best HTML to PDF library for PHP?

Post by flying_circus »

Short of what Astions has posted, my methods are more geared towards using an existing template and then populating the data. You might need to get creative to manage data flowing onto additional pages.

Here is the xFDF example. This is all code based and no extra includes or modules. This method populates pre-determined pdf form fields.

Code: Select all

<?php
  /*
   * createXFDF
   * 
   * @param string $file The pdf file - url or file path accepted
   * @param array $info data to use in key/value pairs no more than 2 dimensions
   * @param string $enc default UTF-8, match server output: default_charset in php.ini
   * @return string The XFDF data for acrobat reader to use in the pdf form file
   */
  function createXFDF($file,$info,$enc='UTF-8')
  {
    $data = '<?xml version="1.0" encoding="' . $enc . '"?>' . "\n" . '<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">' . "\n";
    $data .= '<fields>' . "\n";
    
    foreach($info as $field => $val)
    {
      $data .= '<field name="' . $field . '">' . "\n";
        $data .= '<value>'.$val.'</value>'."\n";
      $data .= '</field>'."\n";
    }
    
    $data .='</fields>' . "\n";
    $data .= '<ids original="' . md5($file) . '" modified="' . time() . '" />' . "\n" . '<f href="' . $file . '" />' . "\n" . '</xfdf>'."\n";
    
    return $data;
  }
  
  
  # Test Code
    $file = 'http://server/test/xfdf/order.pdf';
    $info = array('contpanel1' => 'Black',
                  'contpanel2' => 'Red',
                  'contpanel3' => 'Blue',
                  'contpanel4' => 'Green',
                  'contpanel5' => 'Yeller');
                  
    $xfdf = createXFDF($file, $info);
    
    $file_name = "order.xfdf";
    
    header('Content-type: application/vnd.adobe.xfdf');
    header('Content-Disposition: inline; filename="' . $file_name . '"');
    print $xfdf;
?>

In the process of looking for my FDF example, I found that I was actually using another raster/superimpose type called FPDF. http://www.fpdf.org. I can bundle these files and send to you, if you decide to go this route.

Code: Select all

<?php
  ////////////////////////////////
  // Get Post Data
  ////////////////////////////////
    //Materials
      $matCp_1 = strtoupper($_POST['cp1']);
      $matCp_2 = strtoupper($_POST['cp2']);
      $matCp_3 = strtoupper($_POST['cp3']);
      $matCp_4 = strtoupper($_POST['cp4']);
      $matCp_5 = strtoupper($_POST['cp5']);
      
    
  ////////////////////////////////
  // Create new PDF Document
  // Set background as order form
  ////////////////////////////////
  define('FPDF_FONTPATH','font/');
  require_once('includes/modules/fpdf.php');
  require_once('includes/modules/fpdi.php');
  
  class PDF extends FPDI {
    //Page footer
    function Footer() {
      //Position at 1.5 cm from bottom
        $this->SetY(-15);
      //Arial italic 8
        $this->SetFont('Arial','I',10);
      //Page number
        $this->Cell(0,10,'Page '.$this->PageNo().'/{nb}',0,0,'C');
    }
  }
 
  $pdf = new PDF();
  $pdf->AliasNbPages();
  
  $pdf->SetCreator('Fabrikam');
  $pdf->SetAuthor('Fabrikam');
  $pdf->SetTitle('Fabrikam Order Form');
  
  $pdf->SetDisplayMode('real');
  
  $pagecount = $pdf->setSourceFile("order_form.pdf");
  $tplidx = $pdf->ImportPage(1);
  
  $pdf->addPage();
  $pdf->useTemplate($tplidx,0,10,210);
  
  
  ////////////////////////////////
  // Populate order form fields
  ////////////////////////////////
  $pdf->SetFont('Arial','',9);
  
  // Materials
    // Container Panel 1
      $pdf->SetXY(26,82.1);
      $pdf->Cell(0,0,$matCp_1);
      
    // Container Panel 2
      $pdf->SetXY(26,85.75);
      $pdf->Cell(0,0,$matCp_2);
      
    // Container Panel 3
      $pdf->SetXY(26,89.50);
      $pdf->Cell(0,0,$matCp_3);
      
    // Container Panel 4
      $pdf->SetXY(26,93.1);
      $pdf->Cell(0,0,$matCp_4);
      
    // Container Panel 5
      $pdf->SetXY(26,96.75);
      $pdf->Cell(0,0,$matCp_5);
    
  ////////////////////////////////
  // Return to Top of Document
  // Output PDF Document
  ////////////////////////////////
  $pdf->SetXY(0,0);
  $pdf->Output("infinity.pdf","I");
  $pdf->closeParsers();
?>


PDFLib can be found at http://www.pdflib.com
Currently you have to buy a license or can down load the source and then compile it. It is a module, so it may not be an option.

PDFLib example (Raster / Superimpose method):
I've removed most of code from this example. I'm sure you can clean it up and figure it out. You can see that its mostly just setting an X/Y coord and then printing out your data.

Code: Select all

<?php
  # Load Site Config File
    require_once('includes/configuration.php');
    
  # Begin Output Buffering
    if(GZIP_COMPRESSION == "true" && extension_loaded('zlib')) {
      ini_set('zlib.output_compression_level', GZIP_COMPRESSION_LEVEL);
      ob_start();
    }
    
  # Includes
    require_once('includes/classes/class.db.php');
    
  # Create Database Object
    $db = new db();
    
  # Declare Variables
    $rigId = (isset($_POST['rigId']) ? $_POST['rigId'] : '');
    $rig = array();
    $timestamp = strtotime("now");
 
$infile    = "order.pdf";
$searchpath = PDF_FILE_PATH;
$license = "";
$width     = 612.0;
$height    = 792.0;
 
  try {
    $p = new PDFlib();
    $p->set_parameter("license", $license);
 
    /*  open new PDF file; insert a file name to create the PDF on disk */
      if ($p->begin_document("","") == 0) {
        die("Error: " . $p->get_errmsg());
      }
      
      $p->set_parameter("SearchPath", $searchpath);
    
    /* This line is required to avoid problems on Japanese systems */
      $p->set_parameter("hypertextencoding", "winansi");
 
    /* Set PDF Info */
      $p->set_info("Creator", "order.php");
      $p->set_info("Author", "Fabrikam");
      $p->set_info("Title", "Fabrikam Order Form");
 
    /* $pdi = PDF Import from an existing PDF file */
      $pdi = $p->open_pdi($infile, "", 0);
      if (!$pdi) {
        die("Error: " . $p->get_errmsg());
      }
 
      $p->set_parameter("topdown", "true");
      $p->begin_page_ext($width, $height, "");
    
 
    /* open_pdi_page($pdi,$pageNumber,"") */
      $page = $p->open_pdi_page($pdi, 1, "");
    
      if (!$page) {
        die("Error: " . $p->get_errmsg());
      }
    
      $p->fit_pdi_page($page, 0, $height, "");
 
// experimental
  /* Populate Form */
      // Set Font and Font Size
        $font = $p->load_font("Arial", "winansi", "");
        $fontBold = $p->load_font("Arial Bold", "winansi", "");
        $fontBlack = $p->load_font("Arial Black", "winansi", "fontstyle bold");
        $p->setfont($font, 9);
        
  // Timestamp
    $p->set_text_pos(250, 790);
    $p->show("Printed On: " . date("m/d/Y - h:i:s A",$timestamp));
    
  // Materials
    // Cordura/Para-pak
      $p->setfont($fontBlack, 9);
      if($rig['cnt_material'] == 'CORDURA') {
        $p->set_text_pos(116, 144);
        $p->show("X");
      } else if($rig['cnt_material'] == 'PARAPAK') {
        $p->set_text_pos(194, 144);
        $p->show("X");
      } else if($rig['cnt_material'] == 'MESH') {
        $p->set_text_pos(272, 144);
        $p->show("X");
      }
      $p->setfont($font, 9);
      
  // Container Color
    // Panel 1
      $p->set_text_pos(80, 212);
      $p->show($rig['cnt_panel1']);
    // Panel 2
      $p->set_text_pos(80, 223);
      $p->show($rig['cnt_panel2']);
    // Panel 3
      $p->set_text_pos(80, 234);
      $p->show($rig['cnt_panel3']);
    // Panel 4
      $p->set_text_pos(80, 245);
      $p->show($rig['cnt_panel4']);
    // Panel 5
      $p->set_text_pos(80, 256);
      $p->show($rig['cnt_panel5']);
    // Backpad
      $p->set_text_pos(80, 277);
      if($rig['cnt_material'] == 'MESH') {
        $p->show('MESH');
      } else {
        $p->show($rig['cnt_backpad']);
      }
      
  // Vertical text on Left Edge
    // Name
      $p->fit_textline($rig['cus_firstname'] . ' ' . $rig['cus_lastname'],25,725,"orientate west");
    // Serial Number
      $p->fit_textline($rig['cnt_serialNumber'],25,450,"orientate west");
//
 
  /* finish the first page */
    $p->close_pdi_page($page);
    $p->end_page_ext("");
 
    $p->end_document("");
    $p->close_pdi($pdi);
 
    $buf = $p->get_buffer();
    $len = strlen($buf);
    
    header("Content-type: application/pdf");
    header("Content-Length: $len");
    header("Content-Disposition: inline; filename=foo.pdf");
    print $buf;
 
  }
  catch (PDFlibException $e) {
    die("PDFlib exception occurred in quickreference sample:\n" .
  "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
  $e->get_errmsg() . "\n");
  }
  catch (Exception $e) {
    die($e);
  }
?>

Hopefully one of these will work for you. :)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: The best HTML to PDF library for PHP?

Post by Christopher »

That is a lot of code. Thank you. I need to look through it all to understand what your are doing in each one.

For the GIF in a PDF idea, wouldn't the file be very large?
(#10850)
Post Reply