Gzip'li dosyanın Content-Length nasıl belirlenir?

3 Cevap php

Şu anda bana mod_gzip veya mod_deflate olanak bırakmayacak bir sunucudan CSS ve JS dosyaları hizmet etmeye çalışıyorum. Yani GZIP ile sıkıştırmak ve kullanıcıya geri dönmek için küçük bir PHP komut dosyası yazdı.

Örnek Kod:

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

Ben şu anda burada iki sorun yaşıyorum. İlk ben sorun içerik uzunluğu tarayıcısını bilgilendirmek için sıkıştırılmış dosyanın çıkan boyutunu belirlemek yaşıyorum, olduğunu. Normalde, ben bu satırı içerir:

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

Ben yaparsam daha fazla veri beklemek çalışırken Ama, tarayıcı kilitleniyor. Toplam boyutunu hesaplamak için bir yolu var mı? Yoksa bu başlık yönergesini görmezden gerekir.

Diğer konu Firefox'ta bu PHP dosyasını görüntülemek zaman, bana sonucu indirmek için çalışır, olduğunu. Ben beklediğiniz gibi Chrome, sadece görüntüler. Herhangi bir öneriniz?

Edit: Soapbox sayesinde, bu ile kodun sonuna değiştirilir:

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

Bu içerik-uzunluk için harika çalışıyor! Ama hala dosyayı indirmek yerine görüntülemek için Firefox'u alıyorum. (

Edit Again: İşte modifiye sonu kodu kod, Cletus nezaket olduğunu.

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

Ben Firefox dosyasını indirmek için çalışıyoruz tutar neden anlamaya yeni bir soru başlatmak için gidiyorum.

3 Cevap

Burada sorun, istemci gzip kodlamayı destekler ve ob_gzhandler kullanarak bu kararı delege ettik olup olmadığını bilmeniz gerekir içerik uzunluğunu bilmek olmasıdır. Dan HTTP Headers:

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

Tam sürüm:

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

Bu gzip kodlama konusunda kendinizi alarak daha much iyidir.

Önce tüm gzip yapmak ve (bellekte içeriğini tutan, ya da diske yazma sıkıştırmak gibi ve ardından gzip dosyasını stat'ing ya) sonucunu ölçmek gerekir, daha sonra Content-Length başlığını yazıp dosyayı gönderin içeriği.

Veya kullanmak chunked transfer encoding.

Firefox sorunu çözmek için, sana tarayıcı içeriğini sıkıştırmasını bilir ki header( "Content-Encoding: gzip" ); eklemeniz gerekir düşünüyorum.

Içerik uzunluğuna gelince, sadece bu değeri kapalı bırakarak deneyin, ya da "Transfer-Encoding: chunked" kullanmak için bir yol anlamaya deneyebilirsiniz bu başlık göndermek jsut (yapamazsın, bunun için özel verileri biçimlendirmek gerekir .) Bu ob_end_flush otomatik parçalama sağlayan mümkündür.

Sana wireshark almak ve php komut gönderiyor yakalamak ve ne eksik vb başlıklar, görmek için düzgün davranıyor sunucuya karşılaştırmak öneririz.