Fighting with the widely known fatal error of TCPDF? The error of "Some data has already been output, can't send PDF file" refers to the output buffer of PHP. As you may know as a PHP developer, there is code that generates output in PHP and code that not, for example imagine a method namely getId
that returns a number:
getId();
// [no output]
echo getId();
// Output: 1
So, the conflict with TCPDF is that the library itself once you try to generate the PDF and throw it in the browser using the following code:
<?php
$pdf->Output('example_006.pdf', 'I');
There is surely something in your code that is sending some text or data to the output buffer of PHP before the PDF and therefore the exception is thrown, this is automatically made by the library to prevent the corruption of the generated PDF.
Example of error
To trigger our error in some code with TCPDF, using print_r
or var_dump
to some value will trigger the error. This happens as well if you use echo
or if PHP is throwing a warning, deprecation notice or other kind of errors:
<?php
require __DIR__.'../vendor/autoload.php';
// Create new PDF
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->SetFont("helvetica", '', 10);
$pdf->AddPage();
// Important: this will prevent the generation of the PDF in the browser
// as we are filling the output buffer of PHP
var_dump(array(
"test" => "demo"
));
// create some HTML content
$html = '<h1>HTML Example</h1>
<h2>List</h2>
List example:
<ol>
<li><b>bold text</b></li>
<li><i>italic text</i></li>
<li><u>underlined text</u></li>
<li><b>b<i>bi<u>biu</u>bi</i>b</b></li>
<li><a href="http://www.tecnick.com" dir="ltr">link to http://www.tecnick.com</a></li>
<li>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.<br />Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</li>
<li>SUBLIST
<ol>
<li>row one
<ul>
<li>sublist</li>
</ul>
</li>
<li>row two</li>
</ol>
</li>
<li><b>T</b>E<i>S</i><u>T</u> <del>line through</del></li>
<li><font size="+3">font + 3</font></li>
<li><small>small text</small> normal <small>small text</small> normal <sub>subscript</sub> normal <sup>superscript</sup> normal</li>
</ol>
</div>';
// Output the HTML content
$pdf->writeHTML($html, true, false, true, false, '');
$pdf->lastPage();
$pdf->Output('example_006.pdf', 'I');
The execution of the previous code would generate the following output in the browser:
array(1) { ["test"]=> string(4) "demo" } TCPDF ERROR: Some data has already been output, can't send PDF file
Solution
The first and most common solution, is to search on your code what is the line or code that is generating some output before TCPDF and remove it (mentioned methods as print_r, var_dump, echo etc). If there are no method that generate output but Warnings, deprecation notices or errors from PHP, you need to solve them first. After doing that, the PDF should be generated without any issue.
If for some reason, you cannot track from where the output is being generated, then you can use a very simple trick (however very tricky) that is cleaning the output buffer of PHP before generating the PDF with the Output method of TCPDF:
// Clean any content of the output buffer
ob_end_clean();
// Send the PDF !
$pdf->Output('example_006.pdf', 'I');
This will immediately work, however it is a problem if you want to debug the content of variables in the browser with the mentioned methods that generate content in the output. For example, if you clean the output buffer but you want to see the content of a variable with the following code:
// Debug the content of some variable
var_dump(array(
"data" => "demo"
));
// Clean any content of the output buffer
ob_end_clean();
// Send the PDF !
$pdf->Output('example_006.pdf', 'I');
You will never see the output of var_dump
as we are cleaning the buffer after. So the best solution is to search from where the output buffer is being filled with undesired data and remove it.
Happy coding !