Вопрос

Сейчас я пытаюсь обслуживать файлы CSS и JS с сервера, который не позволяет мне включать mod_gzip или mod_deflate . Поэтому я написал небольшой PHP-скрипт для сжатия с помощью GZIP и возврата пользователю.

Пример кода:

$filename = "style.css";

if (!file_exists($filename) || !($info = stat($filename))) {
  header("HTTP/1.1 404 Not Found");
  die();
}

header("Date: ".gmdate("D, j M Y H:i:s e", time()));
header("Cache-Control: max-age=2592000");
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime']));
header("Etag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime']));
header("Accept-Ranges: bytes");
header("Cache-Control: Expires ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000));
header("Content-Type: text/html");

ob_start("ob_gzhandler");
echo file_get_contents($filename);
ob_end_flush();

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

header("Content-Length: ".$info["size"]);

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

Другая проблема заключается в том, что всякий раз, когда я просматриваю этот файл PHP в Firefox, он пытается загрузить результат. В Chrome он просто отображает его так, как я и ожидал. Есть предложения?

Изменить. Благодаря SoapBox я заменил конец кода следующим образом:

header("Content-Encoding: gzip");
$compressed = gzencode(file_get_contents($filename), 5);
header("Content-Length: ".strlen($compressed));
die($compressed);

Это прекрасно работает для длины контента! Но я все еще заставляю Firefox загружать файл, а не отображать его. : (

Отредактируйте снова . Здесь представлен модифицированный код конца кода, предоставленный Cletus.

// Start buffered output
ob_start();
// Check for gzip capability
if (stripos(

Сейчас я пытаюсь обслуживать файлы CSS и JS с сервера, который не позволяет мне включать mod_gzip или mod_deflate . Поэтому я написал небольшой PHP-скрипт для сжатия с помощью GZIP и возврата пользователю.

Пример кода:

$filename = "style.css";

if (!file_exists($filename) || !($info = stat($filename))) {
  header("HTTP/1.1 404 Not Found");
  die();
}

header("Date: ".gmdate("D, j M Y H:i:s e", time()));
header("Cache-Control: max-age=2592000");
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime']));
header("Etag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime']));
header("Accept-Ranges: bytes");
header("Cache-Control: Expires ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000));
header("Content-Type: text/html");

ob_start("ob_gzhandler");
echo file_get_contents($filename);
ob_end_flush();

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

header("Content-Length: ".$info["size"]);

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

Другая проблема заключается в том, что всякий раз, когда я просматриваю этот файл PHP в Firefox, он пытается загрузить результат. В Chrome он просто отображает его так, как я и ожидал. Есть предложения?

Изменить. Благодаря SoapBox я заменил конец кода следующим образом:

header("Content-Encoding: gzip");
$compressed = gzencode(file_get_contents($filename), 5);
header("Content-Length: ".strlen($compressed));
die($compressed);

Это прекрасно работает для длины контента! Но я все еще заставляю Firefox загружать файл, а не отображать его. : (

Отредактируйте снова . Здесь представлен модифицированный код конца кода, предоставленный Cletus.

<*>

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

SERVER['HTTP_ACCEPT_ENCODING'], "gzip") !== false) { ob_start("ob_gzhandler"); echo file_get_contents($filename); ob_end_flush(); } else echo file_get_contents($filename); // Write the content length header('Content-Length: '.ob_get_length()); ob_end_flush();

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

Это было полезно?

Решение

Проблема здесь в том, что для того, чтобы узнать длину контента, вам нужно знать, поддерживает ли клиент кодировку gzip, и вы делегировали это решение с помощью ob_gzhandler. Из заголовков HTTP :

ob_start();
ob_start('ob_gzhandler');

  ... output the page content...

ob_end_flush();  // The ob_gzhandler one

header('Content-Length: '.ob_get_length());

ob_end_flush();  // The main one

Полная версия:

$filename = "style.css";

if (!file_exists($filename) || !($info = stat($filename))) {
  header("HTTP/1.1 404 Not Found");
  die();
}

header("Date: ".gmdate("D, j M Y H:i:s e", time()));
header("Cache-Control: max-age=2592000");
header("Last-Modified: ".gmdate("D, j M Y H:i:s e", $info['mtime']));
header("ETag: ".sprintf("\"%x-%x-%x\"", $info['ino'], $info['size'], $info['mtime']));
header("Accept-Ranges: bytes");
header("Expires: ".gmdate("D, j M Y H:i:s e", $info['mtime']+2592000));
header("Content-Type: text/css"); // note: this was text/html for some reason?

ob_start();
ob_start("ob_gzhandler");
echo file_get_contents($filename);
ob_end_flush();
header('Content-Length: '.ob_get_length());
ob_end_flush();

Это намного лучше, чем самостоятельно решать проблему кодировки gzip.

Другие советы

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

Или используйте кодировку фрагментированного перевода .

Чтобы решить вашу проблему с Firefox, я думаю, вам нужно включить заголовок (" Content-Encoding: gzip "); , чтобы браузер знал, как распаковать содержимое.

Что касается длины контента, вы можете просто отключить это значение или попытаться найти способ использовать " Transfer-Encoding: chunked " (Вы не можете отправить этот заголовок, вам нужно отформатировать данные специально для него). Возможно, ob_end_flush автоматически разрешит разбиение на фрагменты.

Я рекомендую вам получить wireshark и захватить то, что отправляет ваш php-скрипт, и сравнить его с правильно работающим сервером, чтобы увидеть, какие заголовки и т. д. отсутствуют.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top