I'm trying to use dompdf in my Joomla 3 component, but the PDf that it generates to download is always corrupt. I have opened the PDF file in a text editor and found that the reason for the corruption is that it is including all the headers, links, stylesheets and javascript from joomla, even though I'm ionly passing teh html that i need.
The code I'm using in my joomla component view (the default.php template) is :
<?php
defined('_JEXEC') or die('Restricted access');
ob_start();
?>
<div class="qp-div1">
<table class="table table-bordered">
<thead>
<tr>
<th colspan="2">Account Status</th>
</tr>
</thead>
<tbody>
<tr>
<th>Reference</th>
<td><?php echo $this->userdetails['cardcode']; ?></td>
... more html
<?php
require_once('dompdf/autoload.inc.php');
use Dompdf\Dompdf;
$html = ob_get_contents();
$dompdf = new Dompdf();
$dompdf->setPaper('A4', 'portrait');
$dompdf->setBasePath('');
$dompdf->loadHtml($html);
$dompdf->render();
$dompdf->stream('order');
ob_flush();
ob_end_clean();
?>
Even though I was passing only the HTML I wanted to dompdf->loadHtml when you ran dompdf->stream it ended up using all the joomla html including all teh stylesheets, javascript anf more.
When I use dompdf->output() to dump the output to a file the file is actually okay, so it is only the use of dompdf->stream that has the issue.
The code I used to dump the pdf was inserted before the stream command and looked like this :
$file_to_save = '/temp/pdf/file.pdf';
file_put_contents($file_to_save, $dompdf->output());
$dompdf->stream('order');
Is there anything I can do to stop the $dompdf->stream command from using includding all the Joomla html ?
Cheers
I have fixed my issue by using an additional file within my compnent, but not loading the page into joomla (to avoid the extra headers etc.).
So my solution (in case anyone else wants to do the same) is :
- Use ob_start, ob_flush and ob_end_clean in the original view to capture the html I want to use in the pdf.
- Create a form at the bottom of the page which urlencodes the data I want and posts this data to a new page (COPMPONENT/libraries/downloadfile.php in my case).
- The form posts the data to the new page and teh new page simoply generates the PDF and passes it back to the browser, whereupon it gets download.
This is perfect for me as no additional file is generated on the server (which avoides issues with security and permissions).
It also means that the PDF is only generated if the end use clicks on the download PDF button (in the new form) at the bottom of the page, so there is no unnessacary processing.
The new code is as follows:
1. In my view (file tmpl/default.php)
<?php
defined('_JEXEC') or die('Restricted access');
ob_start();
?>
<div class="qp-div1">
<table class="table table-bordered">
<thead>
<tr>
<th colspan="2">Account Status</th>
</tr>
</thead>
<tbody>
.... more html
</tbody>
</table>
</div>
<?php
$html .= ob_get_contents();
$html = urlencode($html);
ob_flush();
ob_end_clean();
?>
<form method="POST" action="/components/com_questportal/libraries/downloadfile.php" >
<input type="hidden" name="dlname" value="<?php echo $this->userdetails['cardcode'] . '_status'; ?>" >
<input type="hidden" name="dlhtml" value="<?php echo $html; ?>" >
<input type="hidden" name="dlo" value="landscape" >
<input type="image" src="/media/com_questportal/images/downloadaspdf.png" alt="Submit">
</form>
So this shows the ob_start(), then the ob_get_contents where I store my html code for the PDF file.
I then use ob_flush and ob_end_clean to stop the output buffering.
You can also see that I urlencode the HTML received from the ob_get_contents and pass this into my form at the bottom of the page.
I also pass the orientation and name over via the form (as these are all used in the downloadfile.php file).
The next bit of code is the downloadfile.php which is posted to from my form. This page is very simple and just consists of :
<?php
$html = urldecode($_POST['dlhtml']);
$name = $_POST['dlname'];
$orientation = $_POST['dlo'];
require_once('dompdf/autoload.inc.php');
use Dompdf\Dompdf;
$dompdf = new Dompdf();
$dompdf->setPaper('A4', $orientation);
$dompdf->setBasePath('');
$dompdf->loadHtml($html);
$dompdf->render();
$dompdf->stream($name);
?>
So when a user clicks on the download pdf image at the bottom of my page it loads the downloadfile.php page, streams the output to the browser then closes to page (i.e. it never actually displays the downloadfile.php page).
Cheers
Try clearing output buffer before flushing output like in the example below
<?php
defined('_JEXEC') or die('Restricted access');
$html = '<div class="qp-div1">
<table class="table table-bordered">
<thead>
<tr>
<th colspan="2">Account Status</th>
</tr>
</thead>
<tbody>
<tr>
<th>Reference</th>
<td>'.$this->userdetails['cardcode'].'</td>
</tr>
</tbody>
</table>';
require_once('dompdf/autoload.inc.php');
ob_clean();
use Dompdf\Dompdf;
$dompdf = new Dompdf();
$dompdf->setPaper('A4', 'portrait');
$dompdf->setBasePath('');
$dompdf->loadHtml($html);
$dompdf->render();
$dompdf->stream('order');
ob_end_flush();
?>