tecnickcom / TCPDF

Official clone of PHP library to generate PDF documents and barcodes
https://tcpdf.org
Other
4.18k stars 1.51k forks source link

Fix to error: Some data has already been output, can't send PDF file #596

Open shawe opened 1 year ago

shawe commented 1 year ago

In some situations that I can't explain what is causing the issue exatly, appears this error.

When you disable zlib.output_compression in php.ini you can see the error, but if is not disabled, you get a PDF.

With zlib.output_compression_level = 0 and zlib.output_compression = on, the file downloaded was type: gzip compressed data, max speed, from Unix, original size modulo 2^32 23299

But if on top of https://github.com/tecnickcom/TCPDF/blob/main/tcpdf.php#L7704 you add the line

ob_end_clean();

The file downloaded was type: PDF document, version 1.7, 1 pages

This was expected for the end user.

HariharanUmapathi commented 1 year ago

@shawe can you send you code example causes issue or video some thing to view what happens in your environment couldn't understand exactly what happened

from your message only one thing i can get is some issue with compression

can you eloborate your issue with example ?

shawe commented 1 year ago

This problem start happening on a customer installation of unmodified PrestaShop 1.7. Some times the problem happens generating an invoice, and some times not happens. This problem starts happening without any change, 3 or 4 years that this site was working.

I try to debug it better, but I can't found more information or details that I can give you. Seems to be related at some garbage generated and not collected, but I can't found or see it on any place. And believe me that I try it to see it, because all this kind of issue normally ends closed without accept the fix because can't be reproduced.

My colleague Adan who is the sysadmin, found that the zlib compression to speed up a little the site, was hidding this issue, and tracing the problem without that option enabled, I found that is generated near the line that I reported you, and is solved adding the ob_end_clean() like I found on other similar problems.

If you look for this problem "prestashop issue generating pdf invoice" found a lot of issue related, and the solution was always adding this line on some place.

In that case, this code project it's an external dependency, and the issue is not launched until a function for generated the PDF is called. To me, this means that problem starts when this code is called and happens inside of it. I don't know where and why, I only know that only with what I share you on this issue, solve the problem for ower customer.

Same type of problem that I look for you @HariharanUmapathi , an all solutions are using ob_end_clean() before flushing the file content to the end user:

Adding this line don't brake anything to your cide, and is not changing anything that was generated with your library, but at least, prevent this kind of strange issue that seems to be very hard to reproduce.

shawe commented 1 year ago

An not, the issue is not with the compression, the compression was hidding the problem. The problem is that the result PDF generated with your library, when have some content before the header, the PDF generated results corrupted.

The browser Google Chrome opens the bad PDF without problems (inline or downloaded), Linux PDF viewers I tested all open it without problems, but a lot of Windows PDF reader, have issues with it, saying that it's a corrupted file.

The generated file ends to be considered a corrupted file, only with this little change.

Based on documentation: https://www.php.net/manual/en/function.ob-end-clean.php You think that your code is working well, if only was discarting garbage content that is not expected to be at this point?

I can understand that people working on TCPDF wants to verify an reproduce the problem before solve it, but I don't know how the problem is generated, I only know what I need to change to solve it. And I think that the explanation is enought to ensure if I'm wrong or not with my previous question.