php - 如何确定压缩文件的内容长度?

标签 php http-headers gzip header

现在我正在尝试从不允许我启用 mod_gzipmod_deflate 的服务器提供 CSS 和 JS 文件。所以我写了一个小的 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"]);

但是,如果我这样做,浏览器会在尝试等待更多数据时挂起。有没有办法计算总大小?或者我应该忽略这个 header 指令。

另一个问题是,每当我在 Firefox 中查看此 PHP 文件时,它都会尝试让我下载结果。在 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($_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 委托(delegate)了该决定。来自 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

完整版:

$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 编码问题

关于php - 如何确定压缩文件的内容长度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/815961/

相关文章:

php - 谁能帮我看看 php 和 mysql 的排名吗?

java - 如何将上次修改日期与文件上次修改日期进行比较?

ruby - 如何逐行读取 Ruby 1.8.7 中的 gzip 文件?

c - 如何在 C 中顺序解析 gzip 压缩的文本文件而不先完全解压缩

c++ - boost iostreams 可以即时读取和压缩 gzip 文件吗?

php - PayPal IPN - 无法接收电子邮件通知

php - 如何在 PHP 函数内执行 SQL 查询

php - strtotime 1 个月或更早的问题

php - Safari 不发送 "If-Modified-Since"和 "If-None-Match" header

asp.net - 为什么 ASP.NET 框架会在响应中添加 'X-Powered-By:ASP.NET' HTTP header ?