返回预先压缩的静态内容,而不是动态地压缩它

时间:2012-03-01 21:23:56

标签: php database json gzip

我在数据库中索引了很多静态JSON文本内容。其中一些内容大于20K。 Web页面通过Ajax请求此内容,并调用PHP文件以获取数据库中的数据。

当然,可以动态地对返回的内容进行gzip,但我想知道是否可以获取预先压缩的内容并直接从PHP返回。换句话说,我可以预先gzip条目并将它们存储在数据库本身,而不是全文。

这可能吗?如果是,我如何在PHP中指出返回的内容是gzip二进制文件?我使用echo作为纯文本,但是我应该将哪个命令用于二进制数据?我不是PHP专家。感谢。

4 个答案:

答案 0 :(得分:2)

是的,有可能。

您需要通过header功能修改HTTP标头(内容类型,内容长度,传输编码)。

但要注意,您需要解析客户端提出的接受传输编码(deflate,gzip等)并处理所有。如果您将deflate发送到gzip客户端,反之亦然,它将无法按预期工作。

另外,请记住gzip传输编码和gzip文件格式之间存在差异。您可能需要找到一个在PHP中实现此功能的库,或者自行完成这项工作。

无论哪种方式,祝你好运!

答案 1 :(得分:2)

你也会回应gzip压缩数据。 echo只是“将这些字节写入输出缓冲区”。如果需要,您可以回显图像。有趣的是,你告诉浏览器如何处理数据。这是HTTP响应标头的来源。您需要发送Content-Encoding标头。但是你需要确保客户端能够理解gzip,因为它可以工作。您还应该知道,正在使用两种不同的压缩算法:DEFLATE和GZIP。

<?php
$data = fetchGzippedDataFromDatabase();
if (stripos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') !== false) {
  header('Content-Encoding: gzip');
  header('Content-Length: ' . strlen($data));
  echo $data;
} else {
  // client does not accept gzipped data
  echo gzdecode($data);
  // or gzinflate() or gzuncompress() 
  // depending on what you used to compress in the first place
}

您可能需要考虑使用反向代理(nginx,varnish,squid,...)并让它们处理输出压缩。

答案 2 :(得分:2)

由于内容是静态的,我建议你完全循环“从db获取”步骤并尝试一种支持gzip编码响应或缓存gzip压缩版本的缓存机制。

Here is a link给那些为Apache做过这件事的人。另一种解决方案是Varnish

答案 3 :(得分:2)

Apache Web服务器替代

首先,如果您使用Apache Web Server,则可能需要启用和配置mod_deflate。它会在将内容压缩发送到客户端之前对其进行处理。

PHP备选方案#1

如果没有,那么您可以使用ob_gzhandler(PHP 4&gt; = 4.0.4,PHP 5)来激活gzip输出缓冲区。

if(!ob_start("ob_gzhandler")) ob_start();
echo $json;

PHP备选方案#2

另一种可能性(未经测试)可能是将内容缓存在磁盘上,而不是将gzip内容放入数据库中,如果这些内容更多地以未压缩格式使用。使用gzencode

$json = array('id' => $id, 'content' => $content);
$file = '/tmp/' . $json['id'] . '.json';
if(!file_exists($file)) {
  $gzip = gzencode($json['content']);
  file_put_contents($file, $gzip);
} else {
  $gzip = file_get_contents($file);
}
header('Content-Encoding: gzip');
header('Content-Length: '.strlen($gzip));
echo $gzip;

这种方式可能仅适用于输出gzip压缩内容,并且可能无法在所有浏览器中使用。

PHP替代方案#2.5

当浏览器仅接受来自磁盘缓存的gzip压缩内容时。

$json = array('id' => $id, 'content' => $content);
if( strpos($_SERVER["HTTP_ACCEPT_ENCODING"],'gzip') !== false ) {
  $file = '/tmp/' . $json['id'] . '.json';
  if(!file_exists($file)) {
    $gzip = gzencode($json['content']);
    file_put_contents($file, $gzip);
  } else {
    $gzip = file_get_contents($file);
  }
  header('Content-Encoding: gzip');
  header('Content-Length: '.strlen($gzip));
  echo $gzip;
} else {
  echo $json['content'];
}