2

Я прочитал несколько статей о настройке длины содержимого файла, который будет обслуживаться. Он имеет некоторые преимущества по сравнению с загружаемыми файлами. Сервер обслуживает куски (не знаю, какой размер куска в любом случае), когда длина содержимого неизвестна.PHP ob_gzhandler, установка Content-Length отключает вывод gzipped

В PHP я использую ob_gzhandler для gzip html, js и css-файлов и другого текстового контента. Установка содержимого длины содержимого перед выходом gzip приводит к странным побочным эффектам, поскольку длина не соответствует длине gzip-выхода. Я замечаю задержку или браузер сообщает об ошибке кодирования.

Я видел трюк (также на stackoverflow), чтобы установить длину содержимого после сжатия gzip, чтобы быть уверенным, что он сообщает правильный размер. Но когда я это делаю, контент больше не сжимается.

Вопрос в том, правильно ли это поведение? Содержимое gzipped всегда отправляется chuncked? Является ли длина содержимого необходимой только для файлов, которые не являются gzipped?

Вот некоторые фрагментов кода:

Результатов в сжате GZIP и фрагментированной передача файлов:

ob_start('ob_gzhandler'); 
echo $sResult; 

Результаты в нормальной передаче файлов с содержанием длиной указанной (но ожидать gzipped и контент-длина):

ob_start('ob_gzhandler'); 
echo $sResult; 
header('Content-Length: '.ob_get_length()); 

Вот некоторые фотографии из результатов заголовка HTTP: Gzipped and Chuncked

Expect Gzipped but normal transfer when set content-length

+0

Возможный дубликат [Как определить длину содержимого gzip-файла?] (Http://stackoverflow.com/questions/815961/how-to-determine-the-content-length-of-of- a-gzipped-file) –

+0

Это не дубликат, потому что он говорит о gzipped FILE. Кроме того, это может быть файл, но он касается обслуживания контента, а не конкретного файла. Хотите знать, почему он не работает так, как я описал здесь. Не знал, что он полагается на аналогичный метод. Все еще не знаю/понять, ПОЧЕМУ он работает. Файл CSS, который я использовал в этом примере, представляет собой несуществующий файл, потому что он \t составлен из нескольких файлов CSS. – Codebeat

+0

Он работает, потому что он использует два уровня буферизации вывода; при первом 'ob_end_flush()' он очищает внутреннюю буферизацию вывода, принадлежащую 'ob_gzhandler'; то длина содержимого известна ... после этого второй вызов очищает внешний буфер. –

ответ

2

Найдено решение/Хитрость здесь: How to determine the Content-Length of a gzipped file?

Сделано в это:

// clear output buffers 
while(ob_get_level()) 
{ ob_end_clean(); } 

< send http headers here > 

ob_start(); 
ob_start('ob_gzhandler'); 
echo $sResult; 
if(!headers_sent()) 
{ 
    ob_end_flush(); // Flush the output from ob_gzhandler 
    header('Content-Length: '.ob_get_length()); 
    ob_end_flush(); // Flush the outer ob_start() 
} 

Мне непонятно, почему это работает, но, похоже, работает отлично. Содержимое теперь gzipped и имеет длину контента (не chunked).

Чтобы доказать это, вот скриншот:

gzipped and content-length

Ура! ;-)

+0

Спасибо за редактирование jack! – Codebeat