Apache2 with PDF and PHP - "This file does not start with "%PDF-"
This is really tough to troubleshoot - for starters, (please excuse my bluntness, but) this a prime example of what a pipeline should not look like:
- Three different operating systems.
- Probably at least two different versions of PHP.
- Two different webservers.
But anyway, a few general hints on debugging PHP:
- make sure to enable
error_log
andlog_errors
inphp.ini
(setdisplay_errors = Off
) - use the most verbose
error_reporting
- set
access_log
anderror_log
in nginx. - crank up log level in nginx (I'm guessing you use php-cgi or php-fpm, so you should be able to see what status the backend emits when the download attemp fails).
Furthermore:
- You haven't shared how the PDF is generated - are you sure all libraries used here are the same or at least somewhat the same across all systems?
- In any case, just to be sure I would save the PDF on the server before it is offered to download. This allows you to troubleshoot the actual file — to see if the PDF generation actually worked.
- Since you're saving the PDF, I'd see about putting it in a public folder, so you can see if you can just redirect to it after it's generated. And only if this works, then I'd work on a force-download kind of thing.
- I would replicate the production environment in all stages. ;-) You need your dev server to be exactly like the production environment. For your own workstation, I'd recommend a VM (e.g. through Virtualbox with Ubuntu 10.10).
Let me know this gets you somewhere and reply with updates. :-)
Update:
I'd investigate these two headers:
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
Definitely helps with cache busting.
These are the headers, which finally worked in a similar situation in one of my apps:
header("Pragma: public");header("Expires: 0");header("Cache-Control: must-revalidate, post-check=0, pre-check=0");header("Cache-Control: private",false);header( "Content-Type: application/pdf" );header("Content-Disposition: inline; filename=\"YourPDF_" . time() . ".pdf\";");header("Content-Transfer-Encoding: binary");header("Content-Length: ". strlen( $pdfData ) );
I added the time() code to make the filename change each time, so that it likely passes all proxies.
From time to time but seldom, the problem re-appears. Then, we ask our clients to download the file using the browser context menu.
PS: The app uses ezPDF found here: http://www.ros.co.nz/pdf/