Frage

Im Moment versuche ich, CSS und JS-Dateien von einem Server zu dienen, die ich mod_gzip oder mod_deflate ermöglichen werden, nicht zulassen. Also schrieb ich einen kleinen PHP-Skript mit GZIP komprimierte und zurück an den Benutzer.

Beispielcode:

$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();

Ich bin mit zwei Problemen jetzt. Die erste ist, Ich habe Probleme die resultierende Größe der komprimierten Datei Bestimmung den Browser der Content-Length zu informieren. Normalerweise würde ich diese Zeile enthält:

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

Aber wenn ich es tue, hängt der Browser beim Versuch, auf weitere Daten zu warten. Gibt es einen Weg, um die Gesamtgröße zu berechnen? Oder soll ich ignoriere diese Header-Richtlinie.

Das andere Problem ist, wenn ich diese PHP-Datei in Firefox zu sehen, versucht, es mir zur Folge haben, herunterladen. In Chrome, zeigt er es so wie ich erwarten würde. Irgendwelche Vorschläge?

Edit: Dank SoapBox, ersetzte ich das Ende des Codes mit diesem:

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

Dies funktioniert gut für den Inhalt Länge! Aber ich bin immer noch Firefox die Datei statt Anzeige zum Download bereit. : (

Bearbeiten wieder: Hier ist der modifizierte End-of-Code-Code, mit freundlicher Genehmigung von Cletus

.
// Start buffered output
ob_start();
// Check for gzip capability
if (stripos($_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();

Ich werde eine neue Frage beginnen, um herauszufinden, warum hält Firefox versucht, die Datei herunterzuladen.

War es hilfreich?

Lösung

Das Problem hierbei ist, dass die Länge des Inhalts wissen, was Sie wissen müssen, ob die Client-gzip-Codierung unterstützt und Sie haben diese Entscheidung delegieren unter Verwendung ob_gzhandler. Von HTTP-Header :

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

Vollversion:

$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();

Dies ist viel besser als sich selbst ausgeben auf der gzip-Codierung unter.

Andere Tipps

Sie müssen zuerst das gesamte gzip tun und das Ergebnis messen (entweder den Inhalt im Speicher zu halten, oder sie auf der Festplatte zu schreiben, wie Sie komprimieren und dann stat'ing die gzip-Datei), schreiben Sie dann die Content-Length-Header und dann Bitte senden Sie den Inhalt der Datei.

oder benutzen segmentierte Übertragungscodierung .

Um Ihr firefox Problem zu lösen, ich glaube, Sie header( "Content-Encoding: gzip" ); müssen enthalten, so dass der Browser den Inhalt zu dekomprimieren kennt.

Wie für die Inhaltslänge, können Sie versuchen, nur diesen Wert aus verlassen, oder versuchen, einen Weg, um herauszufinden, zu verwenden „Transfer-Encoding: Chunked“ (man kann nicht diesen Header jsut zu senden, müssen Sie die Daten zu formatieren für sie speziell). Es ist möglich, dass ob_end_flush automatisch Chunking ermöglicht.

Ich empfehle Ihnen, wireshark erhalten und erfassen, was Ihr PHP-Skript sendet und vergleichen Sie es mit einem richtig verhalten Server zu sehen, welche Header, usw. fehlen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top