Apache2与PDF和PHP - “此文件不以”%PDF-“开头

时间:2011-04-17 14:19:33

标签: php pdf apache2 nginx

我一直试图找出这个错误的原因已经好几周了 - 而且我已经空白了。系统使用PHP生成动态.pdf文件。

我有三台服务器:Dev(带有Apache2的Win7),Test(带有nginx的Ubuntu 10.4)和Live(带有nginx的Ubuntu 10.10)。所有都运行php5和我开发的系统 - 相同的代码。等价,相同的配置。

我有很多浏览器我测试的东西:DevIE(win7,IE8),DevFF(Win7 Firefox 3.5),DevSaf(win,Safari),LaptopFF(WinXP,Firfox 3.5),笔记本电脑IE(WinXP,IE8测试( Ubuntu FF3.5)和用户(主要是Win 7和Win XP上的IE8)。

  • 当我从Test生成PDF时,它可以在所有浏览器中正常工作(除了我无法测试的用户)。
  • 当我从Dev生成PDF时,它从DevIE,DevFF和DevSaf失败,但是从测试工作中调用它。
  • Apache2始终在同一台计算机上失败。
  • 从笔记本电脑上使用FF成功,使用IE8失败(见下文)。

用户正在报告间歇性问题。它失败了,然后重复请求并成功。

失败时......

显示生成的PDF的日志,发送正确类型的大小回复(500KB到1.8MB),结果为200 OK。这是有时,大约10秒后,重复相同的URL - 但这会生成登录屏幕(再次200 OK回复),但只有2K大小。这意味着它是在没有cookie的情况下被要求的。

Adob​​e Reader尝试显示登录页面,并显示不可避免的"This file does not start with "%PDF-"错误消息。

除了我尝试使用笔记本电脑和IE8时 - 然后它失败了,show source显示一个空行的4行html文件!

该系统已经运行了一年多 - 而且大约2个月前才开始改变生产服务器。测试版本此时未更改,但也开始失败。

我尝试过各种各样的标题,但我尝试过的任何标题都没有任何区别。当前的标题集是:

header('Content-Disposition: inline; filename="'.$this->pdfFilename().'"');
header('Content-type: application/pdf');
header("Pragma: public");
$when = date('r',time()+20);  // expire in 20 seconds
header("Expires: $when");

我尝试用附件替换内联。添加和删​​除各种无缓存标头。一切都无济于事。

通过JavaScript在新窗口中请求PDF,并在8秒后刷新。我没有新窗口进行测试,没有刷新 - 没有变化。

我有Dev服务器提供的一些(小)PDF。所以我提出了我能想到的每一个限制。现在它总是失败。

所以我有一台Windows Apache2.2服务器在从同一台机器上浏览时失败,并且在从Firefox中的其他机器浏览时成功。

除了浏览器之外,没有涉及代理或缓存机制。

有没有人对可能出现的问题有任何想法?正如我所说的那样,我现在已经测试并消除了近4周的时间,打开和关闭,我还没有确定失败的组件。

2 个答案:

答案 0 :(得分:3)

这对于排除故障非常困难 - 首先,(请原谅我的直率,但是)这是管道不应该是什么样子的一个主要例子:

  • 三种不同的操作系统。
  • 可能至少有两个不同版本的PHP。
  • 两个不同的网络服务器。

但无论如何,有关调试PHP的一些一般提示:

  • 请务必在error_log中设置log_errorsphp.ini(设置display_errors = Off
  • 使用最详细的error_reporting
  • 在nginx中设置access_logerror_log
  • 在nginx中调高日志级别(我猜你使用php-cgi或php-fpm,所以你应该能够看到下载尝试失败时后端发出的状态)。

此外:

  1. 您尚未分享PDF的生成方式 - 您确定此处使用的所有库在所有系统中都相同或至少有些相同吗?
  2. 在任何情况下,只是为了确保在提供下载之前将PDF保存在服务器上。这允许您对实际文件进行故障排除 - 以查看PDF生成是否真正有效。
  3. 由于您要保存PDF,我会看到将其放在 public 文件夹中,因此您可以查看是否可以在生成后重定向到该文件夹​​。只有这样才有效,那么我就会采用强制下载的方式。
  4. 我会在所有阶段复制生产环境。 ;-)您需要您的开发服务器与生产环境完全一样。对于您自己的工作站,我建议使用VM(例如通过Virtualbox with Ubuntu 10.10)。
  5. 让我知道这会让你到达某个地方并回复更新。 : - )

    <强>更新

    我会调查这两个标题:

    header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
    header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
    

    绝对有助于缓存破坏。

答案 1 :(得分:0)

这些是标题,最终在我的某个应用中出现类似情况:

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 ) );

我添加了time()代码,每次都会更改文件名,以便它可以通过所有代理。

有时很少会重新出现问题。然后,我们要求客户使用浏览器上下文菜单下载文件。

PS:应用程序使用此处的ezPDF:http://www.ros.co.nz/pdf/