PHP: чтение и представление PDF-файла для загрузки через PHP в некоторых случаях приводит к повреждению файлов - PullRequest
0 голосов
/ 17 октября 2011

Я использую следующее для чтения и представления файла 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 поврежден при попытке открыть его.

Я что-то не так делаю или забыл какой-то важный заголовок? Есть ли лучший способ добиться того же?

UPDATE:

Я отправил файл PDF по электронной почте, и пользователи получили возможность открыть файл. Так что должно быть что-то с тем, как PHP и Nginx обслуживают файл.

Итак, я отключил gzip на Nginx, но ошибка продолжается.

Я также применил подсказки ниже, поэтому код теперь такой:

$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

UPDATE:

Я сделал различие среди файлов:

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>

И я обнаружил, что значение сеанса отражалось в другой части кода, и это было настоящей проблемой с самого начала.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 17 октября 2011

Безусловно, самой распространенной причиной таких проблем является начальный / конечный пробел до / после тегов <?php ?>. Обратите внимание, что вам, вероятно, не нужен тег ?>, который помогает избежать этой проблемы.

Следующая наиболее распространенная причина - забыть вызвать exit / die после вывода файла.

Пожалуйста, проверьте оба вышеперечисленных пункта.

EDIT

Вот как бы я написал этот код:

$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;
1 голос
/ 17 октября 2011

Кроме того, вы должны открыть файл PDF в двоичном режиме:

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

(Или вы можете просто использовать readfile().)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...