PHP:在某些情况下,读取并呈现PDF文件以通过PHP下载会生成损坏的文件

PHP:在某些情况下,读取并呈现PDF文件以通过PHP下载会生成损坏的文件,php,pdf,Php,Pdf,我使用以下内容阅读并向用户呈现PDF文件: $file='file.pdf'; $filepath="/path-to-download-folder/$file"; if(!is_file($filepath)) die('Ops!'); $f=fopen($filepath,'r'); if($f){ header('Cache-Control: no-store, no-cache, must-revalidate'); header('Content-Type: '.mi

我使用以下内容阅读并向用户呈现PDF文件:

$file='file.pdf';
$filepath="/path-to-download-folder/$file";
if(!is_file($filepath)) die('Ops!');
$f=fopen($filepath,'r');
if($f){
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Content-Type: '.mime_content_type($filepath));
    header('Content-Length: '.filesize($filepath));
    header('Content-Disposition: attachment; filename="'.$file.'"');
    fpassthru($f);
}else die("Ops!");
fclose($f);
然而,一些人报告说,当他们试图打开PDF文件时,该文件已损坏

我是做错了什么还是忘记了一些重要的头球?有没有更好的方法实现同样的目标

更新:

我通过电子邮件发送了PDF文件,用户打开了文件。因此,它一定与PHP和Nginx为文件提供服务的方式有关

所以我关闭了Nginx上的gzip,但错误仍然存在

我还应用了下面的提示,因此代码如下所示:

$file='file.pdf';
$filepath="/path-to-download-folder/$file";

if(!file_exists($filepath)){
  header('HTTP/1.1 404 Not Found');
  exit;
}elseif(!is_file($filepath) or !is_readable($filepath)){
  header('HTTP/1.1 403 Forbidden');
  exit;
}else{
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Content-Type: '.mime_content_type($filepath));
    header('Content-Length: '.filesize($filepath));
    header('Content-Disposition: attachment; filename="'.$file.'"');

    set_time_limit(0); // Big files/slow connections may result in incomplete downloads
    readfile($filepath);
    die;
}
但是,我仍然收到此错误:

更新:

我对这些文件进行了区分:

compare -verbose -debug coder Dicas1.pdf Dicas1A.pdf -compose src OUT.tmp
使用此输出:

"gs" -q -dQUIET -dPARANOIDSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=0 "-sDEVICE=pnmraw" -dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r72x72"  "-sOutputFile=/tmp/magick-XXuCqreY" "-f/tmp/magick-XXNkQbcr" "-f/tmp/magick-XXoICX9T"
   **** Warning: File has some garbage before %PDF- .
   **** Error: Cannot find a %%EOF marker anywhere in the file.
   **** Warning:  An error occurred while reading an XREF table.
   **** The file has been damaged.  This may have been caused
   **** by a problem while converting or transfering the file.
   **** Ghostscript will attempt to recover the data.
所以我在Leafpad中打开了它:

原始文件:

%PDF-1.5
%Çì¢
1 0 obj
<<
/Type /Catalog
/Outlines 3 0 R
/Pages 4 0 R
/Dests 5 0 R
/AcroForm 6 0 R
/Names 7 0 R
/Threads 8 0 R
/PageLayout /SinglePage
/ViewerPreferences
<<
/PageDirection /L2R
 >>
>>
endobj
2 0 obj
<<
/Creator (Scribus 1.5.0.svn)
/Producer (Scribus PDF Library 1.5.0.svn)
/Title <>
/Author <>
/Subject <>
/Keywords <>
/CreationDate (D:20111016162546Z)
/ModDate (D:20111016162546Z)
/Trapped /False
>>
endobj
9 0 obj
<<
/Length 154566
/Length1 275572
/Filter /FlateDecode
>>
stream
%PDF-1.5
%Çì¢
10 obj
>>
endobj
20 obj
>
endobj
9.0 obj
>
流动
PHP和Nginx提供的文件:

6Wm931Ja.G46X5WID+1K9G93F.3FD.2IXCWm<br>%PDF-1.5
%Çì¢
1 0 obj
<<
/Type /Catalog
/Outlines 3 0 R
/Pages 4 0 R
/Dests 5 0 R
/AcroForm 6 0 R
/Names 7 0 R
/Threads 8 0 R
/PageLayout /SinglePage
/ViewerPreferences
<<
/PageDirection /L2R
 >>
>>
endobj
2 0 obj
<<
/Creator (Scribus 1.5.0.svn)
/Producer (Scribus PDF Library 1.5.0.svn)
/Title <>
/Author <>
/Subject <>
/Keywords <>
/CreationDate (D:20111016162546Z)
/ModDate (D:20111016162546Z)
/Trapped /False
>>
endobj
9 0 obj
<<
/Length 154566
/Length1 275572
/Filter /FlateDecode
>>
stream
6Wm931Ja.G46X5WID+1K9G93F.3FD.2IXCWm
%PDF-1.5 %Çì¢ 10 obj >> endobj 20 obj > endobj 9.0 obj > 流动
这就是PHP在文件开头放入的垃圾:

6Wm931Ja.G46X5WID+1K9G93F.3FD.2EXCWM

我发现一个会话值在代码的另一部分得到了响应,这是从一开始就存在的真正问题


谢谢。

到目前为止,此类问题最常见的原因是
标记前后的前导/尾随空格。请注意,您可能不需要
?>
标记,这有助于避免此问题

下一个最常见的原因是在输出文件后忘记调用
exit
/
die

请检查以上两点

编辑

下面是我将如何编写代码:

$file = 'file.pdf';
$filepath = "/path-to-download-folder/$file";

if (!file_exists($filepath)) {
  header('HTTP/1.1 404 Not Found');
  exit;
} else if (!is_file($filepath) || !is_readable($filepath)) {
  header('HTTP/1.1 403 Forbidden');
  exit;
}

header('Cache-Control: no-store, no-cache, must-revalidate');
header('Content-Type: '.mime_content_type($filepath));
header('Content-Length: '.filesize($filepath));
header('Content-Disposition: attachment; filename="'.$file.'"');

set_time_limit(0); // Big files/slow connections may result in incomplete downloads
readfile($filepath);

exit;

到目前为止,此类问题最常见的原因是
标记前后的前导/尾随空格。请注意,您可能不需要
?>
标记,这有助于避免此问题

下一个最常见的原因是在输出文件后忘记调用
exit
/
die

请检查以上两点

编辑

下面是我将如何编写代码:

$file = 'file.pdf';
$filepath = "/path-to-download-folder/$file";

if (!file_exists($filepath)) {
  header('HTTP/1.1 404 Not Found');
  exit;
} else if (!is_file($filepath) || !is_readable($filepath)) {
  header('HTTP/1.1 403 Forbidden');
  exit;
}

header('Cache-Control: no-store, no-cache, must-revalidate');
header('Content-Type: '.mime_content_type($filepath));
header('Content-Length: '.filesize($filepath));
header('Content-Disposition: attachment; filename="'.$file.'"');

set_time_limit(0); // Big files/slow connections may result in incomplete downloads
readfile($filepath);

exit;

此外,您还应以二进制模式打开PDF文件:

$f = fopen($filepath, 'rb');

(或者您可以直接使用。)

此外,您应该以二进制模式打开PDF文件:

$f = fopen($filepath, 'rb');

(或者您可以直接使用。)

在文本编辑器或十六进制编辑器中打开时,损坏的文件内部是什么样子?任何PHP错误消息?如何损坏?0字节文件?最后被砍掉了?在某处嵌入了额外的文本?除此之外,请使用
is\u readable()
而不是is\u文件。is_readable更重要,因为有许多文件无法读取,但会通过is_file()检查。我试图获取此信息,但没有从报告此信息的人那里得到任何线索。我在不同的浏览器上尝试了很多次,但总是能得到完整的PDF文件。但我有一个良好的互联网连接,我是一个Linux用户…当在文本或十六进制编辑器中打开时,内部的损坏文件是什么样子的?任何PHP错误消息?如何损坏?0字节文件?最后被砍掉了?在某处嵌入了额外的文本?除此之外,请使用
is\u readable()
而不是is\u文件。is_readable更重要,因为有许多文件无法读取,但会通过is_file()检查。我试图获取此信息,但没有从报告此信息的人那里得到任何线索。我在不同的浏览器上尝试了很多次,但总是能得到完整的PDF文件。但是我有一个很好的互联网连接,而且我是一个Linux用户……嗯,我只在“elseif”之后和“headers”之前插入了一个“else”,尽管这不是真的需要。我做了一个测试,效果很好。现在我将等待客户的任何意见。我会回来公布结果。谢谢。对不起,你能告诉我那在英语中是什么意思吗?因为这是一个我无法复制/粘贴到翻译器中的图像。。。此外,我们真正需要的是原始文件和损坏版本之间的字节比较,以便我们可以尝试找出它是如何/在哪里损坏的。它只是说程序无法打开文件。。。没什么用处。我只是在“elseif”之后和“headers”之前插入了一个“else”,虽然这不是真的需要。我做了一个测试,效果很好。现在我将等待客户的任何意见。我会回来公布结果。谢谢。对不起,你能告诉我那在英语中是什么意思吗?因为这是一个我无法复制/粘贴到翻译器中的图像。。。此外,我们真正需要的是原始文件和损坏版本之间的字节比较,以便我们可以尝试找出它是如何/在哪里损坏的。它只是说程序无法打开文件。。。没什么用。