1
votes

EDIT 2: The problem is not solved; I found a work around by switching to an older version of the file, which was using ezpdf instead of TCPDF, and altering it to get the desired printout (I don't know why only one page in the entire website was changed to TCPDF, but apparently it happened). I would still like to know if there is a way to fix this problem, as the code for TCPDF functions correctly on the server running php 5.2, but not the new server. However, it no longer remains a major priority.

After submitting a request for a PDF, I get nothing; just a blank page. This is all code taken from another server (we are updating php versions to 5.3) and the code works fine on the first server.

Warning: Cannot modify header information - headers already sent (output started at filepath in path/tcpdf.php) TCPDF ERROR: Some data has already been output to browser, can't send PDF file

After some debugging, I noticed that the problem is a 'headers already sent error', which I've encountered several times while updating this site. Most of these errors are fixable using meta http-equiv, as they are mostly just page-refreshes. However, TCPDF uses headers to make the PDF file and force a download.

How can I get case 'D' to work, without needing headers, and if it can't be done, can case 'I' be altered to work without headers instead?

I have tried using ob_clean() before $pdf->output(). I have also tried removing require_once('./common/tcpdf/config/lang/eng.php'). Both of these have fixed problems for other people, and I have extensively researched the topic. I do not think it will work in this case, because I am aware that the website has already started output at this point.

What I want is an alternative to using headers (meta http-equiv?) in case 'D' (preferable) or case 'I' (doable) in the code below, that will give me the same results (a pdf download or a pdf opened in a new tab or window). Unless, of course, there is another fix. If not, I will have to re-write the page without using TCPDF.

EDIT: On the original server, 'generate pdf' causes the page to reload and then, after a long wait (while it queries the database), it forces a download on the user. On the new server, the page is reloaded, the long wait for the query occurs, and then the menu actually breaks (log out is removed and another button is moved beneath the rest of the menu bar) and nothing else happens.

Code taken from tcpdf.php:

case 'I': {
                // Send PDF to the standard output
                echo "<script>console.log('some log');</script>";
                if (ob_get_contents()) {
                    $this->Error('Some data has already been output, can\'t send PDF file');
                }
                if (php_sapi_name() != 'cli') {
                    //We send to a browser
                    header('Content-Type: application/pdf');
                    if (headers_sent()) {
                        $this->Error('Some data has already been output to browser, can\'t send PDF file');
                    }
                    header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
                    header('Pragma: public');
                    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
                    header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');  
                    header('Content-Length: '.$this->bufferlen);
                    header('Content-Disposition: inline; filename="'.basename($name).'";');
                }
                echo $this->getBuffer();
                break;
            }
                case 'D': {
                    // Download PDF as file
                    if (ob_get_contents()) {
                        $this->Error('Some data has already been output, can\'t send PDF file');
                    }
                    header('Content-Description: File Transfer');
                    if (headers_sent()) {

                        $this->Error('Some data has already been output to browser, can\'t send PDF file');
                    }
                    header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
                    header('Pragma: public');
                    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
                    header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
                    // force download dialog
                    header('Content-Type: application/force-download');
                    header('Content-Type: application/octet-stream', false);
                    header('Content-Type: application/download', false);
                    header('Content-Type: application/pdf', false);
                    // use the Content-Disposition header to supply a recommended filename
                    header('Content-Disposition: attachment; filename="'.basename($name).'";');
                    header('Content-Transfer-Encoding: binary');
                    header('Content-Length: '.$this->bufferlen);
                    echo $this->getBuffer();
                    break;
                }
3
Is this happening in the context of a particular PHP framework or CMS? - Ditofry
yes, it is supposed to generate a pdf report as part of league management software. the pdf generation happens after the website has loaded, which is why the headers can no longer be sent. - user3712617
It should tell you what script and what line was responsible for the output that prevents headers from being sent. - halfer
It says there is output started on administration.php:366. Line 366 of that file only has '<?', there is no output. There is an entire section of html above that, which would be output. However, I still don't know how to fix the location of the headers in the tcpdf file to make sure they are called before that output is started. That is why I was hoping for an alternative to the headers instead. - user3712617
Odds are there is some white space before the <?. Also, you should generally use <?php - Jhecht

3 Answers

3
votes

I have seen a lot of references around the Web to use ob_start(), with ob_end_flush() at the end of file. Maybe that works in some situations, although I really don't understood how it would. Not disagreeing - just saying I don't understand, and I did not find it as a solution to the problem.

However, I have found that using ob_start() at the top of the file and ob_end_clean() BEFORE the output should do the trick.

<?PHP
    ob_start();
    // All other content
    ob_end_clean();
    $pdf->Output('MyPDF_File.pdf', 'D');
?>  
2
votes

add

code ob_start() 

in early function and ob_end_flush(); after $pdf->output()

1
votes

There's an echo before setting the header. Just remove:

echo "<script>console.log('some log');</script>";

There may not be eny echo or print before ending the header