我使用下面的代码来读取和呈现一个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;
}
但是我仍然收到这个错误:http://mlkshk.com/r/8FGS
更新:
我在文件中做了一个区别:
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
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
这是PHP放在文件开头的垃圾:
6Wm931Ja.G46X5WID+1K9G93F.3FD.2IXCWm<br>
我发现会话值在代码的另一部分被回显,这是从一开始就是真正的问题。
谢谢。
到目前为止,这种问题最常见的原因是<?php ?>
标记前后的前导/尾随空白。请注意,您可能不需要?>
标记,这有助于避免此问题。
第二个最常见的原因是在输出文件后忘记调用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');
(或者你可以直接用readfile()
)