2010-02-18 2 views
0

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

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.

С помощью Живых заголовков 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 

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

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

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

UPDATE:

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

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

ответ

0

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

0

Попробуйте снять кодировку gzip-Content-Encoding.

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

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

+0

Hi initall, спасибо за ваш ответ. Я думаю, что я сузил проблему. Боюсь, я не могу перезаписать заголовок «Content-Encoding», поскольку он задан веб-сервером. Другими словами, я считаю, что сервер Apache настроен на автоматическое сжатие результата. Итак, теперь, когда я удаляю заголовок Content-Length из моего PHP-скрипта, все работает нормально. И это имеет смысл, поскольку длина контента, заданная PHP, больше не соответствует фактической длине содержимого сжатого файла gzip. Это то, где браузеры, вероятно, немного задохнулись. –

+0

Хорошо, звучит разумно. То, что я также сделал один раз, чтобы избежать двойного нажатия, было чем-то вроде этого поверх главного сценария: 'if (extension_loaded ('zlib') && (! (Bool) ini_get ('zlib.output_compression'))) { ob_start ('ob_gzhandler'); } else { ob_start(); } ' – initall

0

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

Источники:

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

все равно это работает:

/* 
    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);