开发者

PHP: read and present a PDF file to download via PHP is generating corrupted files in some cases

开发者 https://www.devze.com 2023-04-13 08:46 出处:网络
I am using the following to read and present a PDF file to the user: $file=\'file.pdf\'; $filepath=\"/path-to-download-folder/$file\";

I am using the following to read and present a PDF file to the user:

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

However some folks are reporting that the PDF file is corrupted when they try to open it.

Am I doing something wrong or forgetting some important header? Is there a better way to achieve the same?

UPDATE:

I sent the PDF file via email and the users got to open the file. So it must be something with the way PHP and Nginx are serving the file.

So I turned off gzip on Nginx but the error continues.

I also applied the tips bellow so the code is now like this:

$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;
}

However I still am receiving this error: http://mlkshk.com/r/8FGS

UPDATE:

I made a diff among the files:

compare -verbose -debug coder Dicas1.pdf Dicas1A.pdf -compose src OUT.tmp

With this output:

"gs" -q -dQUIET -dPARAN开发者_开发百科OIDSAFER -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.

So I opened it in Leafpad:

Original file:

%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

File served by PHP and 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

So this is the garbage PHP is puting in the begining of the file:

6Wm931Ja.G46X5WID+1K9G93F.3FD.2IXCWm<br>

And I found that a session value was being echoed in another part of the code and that was the real problem since the beginning.

Thanks.


By far and away the most common cause of problems like this is leading/trailing whitespace before/after the <?php ?> tags. Note that you probably don't need a ?> tag, which helps avoid this problem.

Next most common cause is forgetting to call exit/die after outputting the file.

Please check both of the above points.

EDIT

Here is how I would write that code:

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


Also, you should open the PDF file in binary mode:

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

(Or you could just use readfile().)

0

精彩评论

暂无评论...
验证码 换一张
取 消