2013-04-08 6 views
7

У меня проблема, которая много раз поднималась на SO, но я не могу найти решение для моего! Я пытаюсь доставить PDF-файл клиенту, не открывая его в браузере, загрузка файла, но он поврежден, когда я его открываю, и не хватает нескольких байтов из исходного файла. Я попробовал несколько таких методов для загрузки файла, но я просто покажу вам последнее, что я использовал, и надеюсь получить обратную связь.Force Загрузка файла в формате PDF, поврежденный файл

Я также открыл загруженный PDF-файл в текстовом редакторе, и на его вершине нет ошибок php, которые я вижу!

Я также знаю, что readfile() выполняется намного быстрее, но для тестирования я отчаянно хочу получить что-либо, чтобы использовать метод while (! Feof())!

достаточно хаотичный Во всяком случае, Херес-код (взято из why my downloaded file is alwayes damaged or corrupted?):

$file  = __DIR__ . '/reports/somepdf.pdf'; 
$basename = basename($file); 
$length = sprintf("%u", filesize($file)); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="' . $basename . '"'); 
header('Content-Transfer-Encoding: binary'); 
header('Connection: Keep-Alive'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: ' . $length); 

ob_clean(); 
set_time_limit(0); 
readfile($file); 

отметить также была разница в размере файла:

Original: 351,873 bytes 
Downloaded: 329,163 bytes 
+1

Пробовали ли вы 'ReadFile()'? – barbashov

+0

@ DavidC799: Если вы хотите обсудить ответ на предыдущие вопросы, пожалуйста, оставьте там комментарий. Не просто введите здесь какой-то код и скажите нам, что «это не работает». Имейте в виду, только кто-то другой принимал этот ответ, это не должно означать, что код должен работать и на вас. И для целей тестирования, пожалуйста, уменьшите код до минимума, чтобы спровоцировать проблему. Например. нет функции, просто жестко заданное имя файла. Используйте readfile. – hakre

+0

@barbashov Да, я пробовал несколько разных методов. – DavidC799

ответ

7

Убедитесь, что вы не используете какой-либо компрессии обработчики буферизации вывода, такие как ob_gzhandler. У меня был подобный случай, и мне пришлось отключить буферизацию вывода, чтобы это нормально работало.

+0

Действительно, я! Теперь, когда вы упомянули об этом, я видел, как кто-то еще упоминает об этом в другом посте. Попробуй несколько вещей и сообщишь, как это происходит. Извините за хлопот! – DavidC799

+0

Успех! Большое спасибо за вашу помощь, всегда что-то такое простое :( – DavidC799

+0

@ DavidC799: Ну, просто прочитайте другие вопросы, большинство ответов на сайте уже вам нужно их найти;) – hakre

6

Вы используете ob_gzhandler в выходном буфере.

Он работает с gzencoding chunks вывода. Затем выход представляет собой поток закодированных фрагментов.

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

Однако в конце вашего сценария вы отбрасываете оставшийся буфер вместо его промывки.

Используйте ob_end_flush() вместо ob_clean(), и файл проходит полностью и не поврежден.

Вы должны использовать кодировку передачи ob_gzhandler с файловыми загрузками, не имеющими проблем, когда вы не уничтожаете выходной буфер до того, как это могло бы сделать его работу.

Это то же самое, если любая другая выходная буферизация, которая работает chunked, была бы включена.

Пример кода:

$file  = __DIR__ . '/somepdf.pdf'; 
$basename = basename($file); 
$length = sprintf("%u", filesize($file)); 

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename="' . $basename . '"'); 
header('Content-Transfer-Encoding: binary'); 
header('Connection: Keep-Alive'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
header('Pragma: public'); 
header('Content-Length: ' . $length); 

ob_end_flush(); // <--- instead of ob_clean() 

set_time_limit(0); 
readfile($file); 

return; 

(FYI: на самом деле даже ob_end_flush(); не является необходимым, важной частью не только удар выходной-буфер, прежде чем он мог бы сделать это работа)

+0

Я могу подтвердить, что код hakre работает должным образом; спасибо за подробное объяснение – periklis

+0

Также я только что проверил источник readfile() в PHP, и вы должны (если можете) всегда использовать его вместо того, чтобы делать собственное fopen/buffered, как в вопросе. 'readfile()' намного превосходит выходы для загрузки файлов, поскольку он может использовать преимущества в SAPI, которые невозможны в коде userland. – hakre

-1

I сражался с использованием контента, чтобы загрузить PDF-файл за два дня, прежде чем найти решение моей проблемы. Мои файлы PDF также были меньше по размеру и повреждены, однако я мог открыть их в Windows Preview - просто не Adobe. После значительного устранения неполадок я обнаружил, что Adobe ожидает% PDF в первых 1024 байтах файла. Перед созданием заголовков я делал все свои проверки типа файла в моем php-коде. Я достал большую часть кода перед заголовками, и мой PDF-файл был исправлен.

Вы не могли бы быть настраивая это так же, как я сделал, но это может быть та же самая проблема:

http://helpx.adobe.com/acrobat/kb/pdf-error-1015-11001-update.html

Смежные вопросы