Creating PDF files with Html2ps/Html2pdf
Html2ps (also known as Html2pdf) is a free PHP tool wich allows users to create their own PDF files from a complete designed html page. The different between this version and the one from Kalileo (http://bakery.cakephp.org/articles/view/creating-pdf-files-with-cakephp-and-tcpdf) is that this Html2pdf allows complete websites including all css files, images, tables, divs, etc.
Requirements
- CakePHP 1.3.x
- Html2ps op Tufat (http://www.tufat.com/s_html2ps_html2pdf.htm)
- Basic knowledge of CakePHP
Step 1: Download and install Html2ps
- Go to http://www.tufat.com/s_html2ps_html2pdf.htm and download the latest version of Html2ps.
- Unzip the files to the vendor map /app/vendors/html2ps/.
- Open pipeline.class.php and search for "$this->_dispatcher =& new Dispatcher();" and replace it with: "$this->_dispatcher =& new DispatcherPdf();".
- Open dispatcher.class.php and change to following lines: "class Dispatcher {" into "class DispatcherPdf {" and "function Dispatcher() {" into "function DispatcherPdf() {".
Step 2: The Pdf Component
Make a file pdf.php in /app/controllers/components and paste the following code.Component Class:
<?php
class PdfComponent extends Object {
var $p; // The Pdf Class
var $media;
var $filename = 'invoice'; // Without the .pdf
var $output = 'browser'; // browser,file,download
function init() {
// Include the class file and create Html2ps instance
App::import('vendor', 'Html2PsConfig', array('file' => 'html2ps'.DS.'config.inc.php'));
App::import('vendor', 'Html2Ps', array('file' => 'html2ps'.DS.'pipeline.factory.class.php'));
parse_config_file(APP .'vendors'. DS .'html2ps'. DS .'html2ps.config');
global $g_config;
$g_config = array(
'cssmedia' => 'screen',
'renderimages' => true,
'renderforms' => false,
'renderlinks' => true,
'mode' => 'html',
'debugbox' => false,
'draw_page_border' => false
);
$this->media = Media::predefined('A4');
$this->media->set_landscape(false);
$this->media->set_margins(array('left' => 0,
'right' => 0,
'top' => 0,
'bottom' => 0));
$this->media->set_pixels(1024);
global $g_px_scale;
$g_px_scale = mm2pt($this->media->width() - $this->media->margins['left'] - $this->media->margins['right']) / $this->media->pixels;
global $g_pt_scale;
$g_pt_scale = $g_pt_scale * 1.43;
$this->p = PipelineFactory::create_default_pipeline("","");
switch ($this->output) {
case 'download':
$this->p->destination = new DestinationDownload($this->filename);
break;
case 'file':
$this->p->destination = new DestinationFile($this->filename);
break;
default:
$this->p->destination = new DestinationBrowser($this->filename);
break;
}
}
function process($url) {
$this->p->process($url, $this->media);
}
}
?>
The above code is a very basic setup for Html2ps. You can change whatever you want to fit your PDF requirements.Step 3: The Pdf layout
We will use a different layout for the Pdf files then the default.ctp. With this we are able to have a different layout then the website itself. Create the file pdf.ctp in /app/views/layout/ and paste the following code.View Template:
<?php echo $content_for_layout; ?>
You're free to use any css files or images you like. In this example we only use a white paper for the layout.Step 4: The Controller functions
The rendering of the Pdf files happens in a controller function. In this example I use the "Invoices" controller with two functions: view() and download(). The view() displays the normal html file and the download() renders the view in PDF format.Paste the following functions in your controller.
Controller Class:
<?php
class InvoicesController extends AppController {
var $name = 'Invoices';
function view($id = null) {
// Be sure that the current user can download this Invoice...
$this->set('invoiceNumber', '1234');
}
function download($id = null) {
// Include Component
App::import('Component', 'Pdf');
// Make instance
$Pdf = new PdfComponent();
// Invoice name (output name)
$Pdf->filename = 'your_invoice'; // Without .pdf
// You can use download or browser here
$Pdf->output = 'download';
$Pdf->init();
// Render the view
$Pdf->process(Router::url('/', true) . 'invoices/view/'. $id);
$this->render(false);
}
}
?>
Step 5: That's it!
Make a nice view of your invoice in /app/views/invoices/view.ctp and open http://www.fellicht.nl/invoices/download/1234.If you have any questions, suggestions or mistakes in the above article please submit them!








This works perfectly in my computer, but when I test it online it doesn't work. It seems don't recognize any php code.
What could be the problem here?
Thank you!!!
Jorge
Locally, it works fine, but once in the server it doesn't. I tried the other solution below but they didn't work.
Please, help.
Locally, it works fine, but once in the server it doesn't. I tried the other solution below but they didn't work.
Please, help.
[end quote]
By the way, it works on mi computer (with XAMPP) but not in the server.
Need help about it
[end quote]
hi! were you able to find a solution for this? i'm getting same error while trying to create a pdf w/ images and more than 1 table.
i tried to change backtrack_limit and recursion_limit in php.ini but it doesnt seem to take effect in my cakephp app.
i wish someone could post a solution for this. thanks in advance!
[end quote]
updating my post.. i was able to allow my cakephp app to convert html to pdf and download it successfully now.
what i did to correct the fatal error 256 is that i changed the values of backtrack_limit and recursion_limit to 1000000. when i thought it wasnt taking effect in my app, i figured it was because the default line for backtrack and recursion was commented out. so i removed the ';' before the 2 lines, changed the values, saved the php.ini and then restart my wamp.
but then i encountered another error about bytes exhausted. while looking for answers i found a solution in this site http://ask.cakephp.org/questions/view/fatal_error_allowed_memory_size_of_25165824_bytes_exhausted_tried_to_allocate_29_bytes and applied it in my app. after that my download for pdf worked.
maybe this post could help someone who has same problem.
just that i noticed my app is taking time to show the download window. i dunno if there's a way to make it faster. continuing my adventure on this coz this is my first time creating a web app and first time using cakephp.
the pdf file thas generated from class is not opened. i have get the message when i try to open pdf:
"Adobe reader could open "invoice12.pdf" because it is either not a support file type or because the file has been damaged (for example, it was sent as email attachment and was'nt correctly decoded).
hope u wil find solution for me!
thanks,
the pdf file thas generated from class is not opened. i have get the message when i try to open pdf:
"Adobe reader could open "invoice12.pdf" because it is either not a support file type or because the file has been damaged (for example, it was sent as email attachment and was'nt correctly decoded).
hope u wil find solution for me!
thanks,
[end quote]
the pdf file thas generated from class is not opened. i have get the message when i try to open pdf:
"Adobe reader could open "invoice12.pdf" because it is either not a support file type or because the file has been damaged (for example, it was sent as email attachment and was'nt correctly decoded).
hope u wil find solution for me!
thanks,
[end quote]
and i m getting this error
Fatal error: Class 'Media' not found in C:\wamp\www\age\app\controllers\components\pdf.php on line 28
pls i need help.
thx anyway
Fatal Error (256): pcre.pcre.backtrack_limit(100000) and pcre.recursion_limit(100000) too low [APP\vendors\html2ps\xhtml.utils.inc.php, line 51] Code | Context
if (!$html) {
trigger_error('pcre.pcre.backtrack_limit('.ini_get('pcre.backtrack_limit').') and pcre.recursion_limit('.ini_get('pcre.recursion_limit').') too low', E_USER_ERROR);
$html = ""
$open = "]*)?>"
$close = ""
process_html - APP\vendors\html2ps\xhtml.utils.inc.php, line 51
html2xhtml - APP\vendors\html2ps\xhtml.utils.inc.php, line 415
DataFilterHTML2XHTML::process() - APP\vendors\html2ps\filter.data.html2xhtml.class.php, line 9
Pipeline::_layout_item() - APP\vendors\html2ps\pipeline.class.php, line 1144
Pipeline::_process_item() - APP\vendors\html2ps\pipeline.class.php, line 789
Pipeline::process_batch() - APP\vendors\html2ps\pipeline.class.php, line 997
Pipeline::process() - APP\vendors\html2ps\pipeline.class.php, line 957
PdfComponent::process() - APP\controllers\components\pdf.php, line 56
MyController::download() - APP\controllers\my_controller.php, line 696
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 204
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 171
[main] - APP\webroot\index.php, line 84
It takes time to generate the pdf and i see in my chart image folder that two images are generated, so the page is load two times ???
[end quote]
hi! were you able to find a solution for this? i'm getting same error while trying to create a pdf w/ images and more than 1 table.
i tried to change backtrack_limit and recursion_limit in php.ini but it doesnt seem to take effect in my cakephp app.
i wish someone could post a solution for this. thanks in advance!
when i test this component in localhost all is good, but when i upload on 1&1 my pdf generate is empty, and there is no error report.
i hope you will have any solution.
Warning (512): SQL Error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'copy' at line 1 [CORE/cake/libs/model/datasources/dbo_source.php, line 681] Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Query: copy
Any suggestions?
I have this in my view.ctp
so, when the browser download the asociate pdf of this view, the Session array it's empty...
I print the view in other window, and show me the Session array correctly
I need to configure something more????
Best regards...
Gustavo Delgado R.
I have this in my view.ctp
print_r($_SESSION);
so, when the browser download the asociate pdf of this view, the Session array it's empty and show me this...
Array ( [Config] => Array ( [userAgent] => [time] => 1291094594 [timeout] => 10 ) )
I print the view in other window, and show me the Session array correctly
I need to configure something more????
Best regards...
Gustavo Delgado R.
[end quote]
trigger_error(sprintf("Cannot open %s",
$data_id), E_USER_WARNING);
$data_id = "http://localhost:8080/BarcodePortal/departures/deliverynotepdf/1"
$_server_response = null
$_url = "http://localhost:8080/BarcodePortal/departures/deliverynotepdf/1"
FetcherUrl::get_data() - APP\vendors\html2ps\fetcher.url.class.php, line 94
Pipeline::fetch() - APP\vendors\html2ps\pipeline.class.php, line 941
Pipeline::_layout_item() - APP\vendors\html2ps\pipeline.class.php, line 1137
Pipeline::_process_item() - APP\vendors\html2ps\pipeline.class.php, line 790
Pipeline::process_batch() - APP\vendors\html2ps\pipeline.class.php, line 998
Pipeline::process() - APP\vendors\html2ps\pipeline.class.php, line 958
PdfComponent::process() - APP\controllers\components\pdf.php, line 55
DeparturesController::deliverynotepdf() - APP\controllers\departures_controller.php, line 48
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 204
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 171
[main] - APP\webroot\index.php, line 83
I need some help. Thanks in advance
Thanks
I solve this problem with removing ?> on line 58 from pdf.php component
Thanks for the greate helper, but PDF that the class is generating is not opening. I get the following error from Adobe Reader: "Adobe reader could open "invoice12.pdf" because it is either not a support file type or because the file has been damaged (for example, it was sent as email attachment and was'nt correctly decoded).
I have checked html2pdf website, but cannot find anything useful.
Thanks for your help
Sudhir
Is there a way to give the pdf-component temporary rights, change it to act as user with it's rights or create aro for the pdf-component so it would have rights in the acl-database?
Thanks by the way.
I have an error like this :
$tmp_filename = "E:\xampp\htdocs\gestion\app\vendors\html2ps\temp\PS_143.tmp"
$content_type = ContentType
ContentType::$default_extension = "pdf"
ContentType::$mime_type = "application/pdf"header - [internal], line ??
DestinationHTTP::process() - APP\vendors\html2ps\destination._http.class.php, line 12
Pipeline::_output() - APP\vendors\html2ps\pipeline.class.php, line 915
Pipeline::close() - APP\vendors\html2ps\pipeline.class.php, line 366
Pipeline::process_batch() - APP\vendors\html2ps\pipeline.class.php, line 1003
Pipeline::process() - APP\vendors\html2ps\pipeline.class.php, line 957
PdfComponent::process() - APP\controllers\components\pdf.php, line 55
OperationController::telecharger() - APP\controllers\operation_controller.php, line 243
Dispatcher::_invoke() - CORE\cake\dispatcher.php, line 204
Dispatcher::dispatch() - CORE\cake\dispatcher.php, line 171
[main] - APP\webroot\index.php, line 83
Thanks for your help.
regards.
I finally had to put a beforeFilter in my controller:
function beforeFilter()
{
$this->Auth->allow('download','view');
parent::beforeFilter();
}
I have to explicitly autorize both the download and the view actions. After doing this, it no longer gave me a PDF of my login page.
Hope this helps someone...
Fatal error: Cannot redeclare class File in /app/vendors/html2ps/classes/org/active-link/sys/File.php on line 33
You can try to edit the file "/app/vendors/html2ps/classes/org/active-link/sys/File.php" and replace the following lines:
andclass File {
into
class FilePdf {
function File($filename = "", $fileOpenMode = "r") {
into
function FilePdf($filename = "", $fileOpenMode = "r") {
I don't know where this class is used but if you get an error according File class not found you should search for the file/linenumber of the error and replace the classname "File" into "FilePdf".
I got similar problem when i first run the test. It said:
Fatal error: Cannot redeclare class Destination in .....
Eventually there is a model class called Destination in my app. I give a try to rename my class.. my problem solved.
So, not sure you are having same situation where u got the File class somewhere. Hope this could help.
Did I miss something in my setup? I have followed the steps explained.
Thanks in advance.
I'm not sure but maybe the Pdf component is producing a notice error or something like that. If not, you should be sure that you have a give a correct $url parameter in the process function.
$Pdf->process($url_to_html_page); // This is probably in your controller
function view($id = null) {
// It will call the PDF layout
$this->layout = 'pdf';
Fatal error: Call to undefined function parse_config_file() in /home/...../app/controllers/components/pdf.php on line 14
I'm using CakePHP 1.3
Did you place the html2pdf in the correct directory?
/app/vendors/html2ps/
Be sure that the component can include the required files. See this two lines:
App::import('vendor', 'Html2PsConfig', array('file' => 'html2ps'.DS.'config.inc.php'));
App::import('vendor', 'Html2Ps', array('file' => 'html2ps'.DS.'pipeline.factory.class.php'));
Putting this into beforefilter makes it work:
However if i try to limit the access just to the one action, it does not:parent::beforeFilter();
$this->Auth->allow('*');
if ($this->action == 'download'){
parent::beforeFilter();
$this->Auth->allow('*');
}
Running this on 1.2.5 and it works other then the Auth/Acl issue.
I'm not sure why it isn't working but you can try the following:
beforeFilter():
$this->Auth->allow('download');And do the check in your view() function. e.g.:function view($invoice_id = null, $security_hash = null) {
You can set the security hash in your download() function with $this->Invoice->save();.$someInvoice = $this->Invoice->find('first', array('conditions' => array('Invoice.id' => $invoice_id, 'Invoice.checksum' => $security_hash)));
}
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 1400 bytesI got the same error, asked my host to increase the memory limit and now works near perfectly.
The only thing I can't work out (which I suspect is a Html2ps/Html2pdf problem) is whenever I close a PDF created by my site I get asked if I want to save changes. I haven't made any changes (just opened it) so I don't know why that's happening. Or indeed if its happening to anyone else?
Other than that, works great!
I don't think to problem is with Html2pdf but with your PDF Reader. Can you try change this code:
$Pdf->output = 'download';Into this:$Pdf->output = 'browser';Comments are closed for articles over a year old