Проблема с загрузками: медленно и / или не удается

У меня есть следующий скрипт, чтобы позволить посетителю скачать файл:

header( 'Content-Type: application/octet-stream' );
header( 'Content-Transfer-Encoding: binary' );
header( 'Content-Disposition: attachment; filename=' . $fileName );
header( 'Content-Length: ' . filesize( $filePath ) );
header( 'Content-Description: Download' );
header( 'Cache-Control: private' );
header( 'Pragma: no-cache' );
header( 'Expires: 0' );

readfile( $filePath );
exit();

Это не очень хорошо работает. (Я также поместил имя файла в кавычки, тот же результат).

Он ведет себя очень медленно, и иногда загрузка даже останавливается. Особенно в Opera он останавливается на 99% загрузки. Иногда он даже сразу показывает, что выполнено 99%, затем он начинает загрузку и останавливается на отметке 34%.

Сервер является общим хостом, сервером Mac OS X.

С помощью надстройки Live HTTP заголовков Firefox я заметил, что сервер добавляет дополнительные заголовки к ответу:

HTTP/1.1 200 OK
Date: Thu, 18 Feb 2010 09:27:25 GMT
Server: Apache
X-Powered-By: PHP/5.2.12
Content-Transfer-Encoding: binary
Content-Disposition: attachment; filename=test.psd
Content-Length: 398635
Content-Description: Download
Cache-Control: private
Pragma: no-cache
Expires: 0
Content-Encoding: gzip // <-- expecially this one,
Vary: Accept-Encoding // <-- this one,
MS-Author-Via: DAV // <-- and this one
Keep-Alive: timeout=10, max=100
Connection: Keep-Alive
Content-Type: application/octet-stream

Могут ли они быть причиной проблемы?

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

Я действительно довольно невежественен в этом. Ваша помощь является точной. Заранее спасибо.

ОБНОВИТЬ:

Я думаю, что я сузил проблему до узкого места. Веб-сервер GZIP автоматически сжимает вывод. Когда я удалил Content-Length Заголовок из моего PHP-скрипта все начало загружаться гладко. Это имеет смысл: ценность Content-Length больше не соответствует фактическому выводу gzipped. В PHP я прочитал несжатый размер файла, чтобы установить Content-Length заголовок, но после этого Apache сжимает его, и это, вероятно, там, где браузеры задохнулись.

Я задам этот вопрос вопросом о том, как правильно установить Content-Length размер заголовка, когда веб-сервер автоматически сжимает выходные данные.

3 ответа

Решение

Я сузил проблему до узкого места. Веб-сервер GZIP автоматически сжимает вывод. Когда я удалил заголовок Content-Length из моего PHP-скрипта, все стало загружаться гладко. Это имеет смысл: значение Content-Length больше не соответствует фактическому сжатому выводу. В PHP я читал несжатый размер файла, чтобы установить заголовок Content-Length, но после этого Apache сжимает его, и это, вероятно, там, где браузеры подавились.

Попробуйте отключить gzip-Content-Encoding.

использование ob_start() в самом начале вашего сценария; перед настройкой заголовков используйте @ob_end_clean(); и сразу после этого, явно установить header("Content-Encoding:"); попытаться сбросить любую gzip-кодировку, которая может прийти. В конце вашего файла @ob_end_flush();,

Функции буферизации вывода удобны, чтобы сделать настройку заголовка более отказоустойчивой, но, вероятно, не связаны с вашей проблемой. Я просто помню, что столкнулся с проблемами в установке, где код PHP использовал ob_gzhandler, и мне нужно было его сбросить.

Я использую код ниже, и он работает. Говоря по правде, я не понял и все же должным образом весь заголовок, который я отправляю, у меня все еще не было времени для расследования, я нашел объяснения в:

Источники:

http://www.opendesigns.org/forum/discussion/1437/php-download-counter/ http://www.webdeveloper.com/forum/showthread.php?t=115815&highlight=PHP+download+counter http://php.net/manual/en/function.header.php

в любом случае это работает:

   /*
   TODO: still to be read and better understood.
   */

   //no caching (I don't uderstand what is this part useful for)
   header("Pragma: public"); //?
   header("Expires: 0"); //?
   header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); //?
   header("Cache-Control: private", false); //?

   //sending download file
   header("Content-Type: application/octet-stream"); //application/zip can use application/octet-stream that is more generic it works because in now days browsers are able to detect file anyway
   header("Content-Disposition: attachment; filename=\"" . basename($file_serverfullpath) . "\""); //ok
   header("Content-Transfer-Encoding: binary"); //?
   header("Content-Length: " . filesize($file_serverfullpath)); //ok
   readfile($file_serverfullpath);
Другие вопросы по тегам