如何gzip缓存文件使用ob_


How to gzip cached files using ob_

我正在寻找一种方法来gzip我的html的缓存副本,也服务器缓存的版本给用户,这是可能的吗?我到目前为止有这个…

//开头

$filename   = md5($_SERVER['REQUEST_URI']);
$cache_file = $_SERVER['DOCUMENT_ROOT'].'/pagecache/' . $filename . '.htm';
$cache_time = 86400; // 24 hours
if (file_exists($cache_file) &&
time() - $cache_time < filemtime($cache_file)) {
include($cache_file);
exit;
}
ob_start();

//在页脚

$cached = fopen($cache_file, 'w'); 
fwrite($cached, ob_get_contents());
fclose($cached);
ob_end_flush(); 

任何指导将不胜感激。

您不需要压缩每个文件,在php.ini中启用输出压缩,它会自动完成

zlib.output_compression = On

或以

开始输出缓冲区
ob_start('ob_gzhandler');

现在,如果你的缓存的目的是因为speedstorage space,那么不要使用文件系统,只使用Memcached ..它支持内置压缩

$memcache = new Memcache();
$memcache->addserver("127.0.0.1");
$memcache->add($filename, ob_get_contents(), MEMCACHE_COMPRESSED);

这是一个简单的脚本来管理文件缓存和memcache…你可以很容易地扩展到其他类型的存储,如mongoDB或redis

使用文件系统

$storage = new Fcache();
$storage->setDir(__DIR__ . "/cache"); // cache directory

使用Memcache

$storage = new Mcache();
$storage->addserver("127.0.0.1"); // Add Server

你的脚本

$cache = new SimpleCache($storage);
$cache->setTime(5); // 5 sec for demo
if ($data = $cache->get()) {
    echo "Cached Copy <br />'n";
    echo $data;
} else {
    ob_start();
    while(@$i ++ < 10) {
        echo mt_rand();
    }
    $cache->set(ob_get_contents());
    ob_end_flush();
}

您可以看到$storage存储可以是file或memcache,这里是使用的类

SimpleCache

class SimpleCache {
    private $storage;
    function __construct(CacheStorage $storage) {
        $this->storage = $storage;
    }
    public function setTime($time) {
        $this->storage->setTime($time);
    }
    function get() {
        $name = sha1($_SERVER['REQUEST_URI']) . ".cache";
        return $this->storage->read($name);
    }
    function set($content) {
        $name = sha1($_SERVER['REQUEST_URI']) . ".cache";
        $this->storage->write($name, $content);
    }
}
存储

interface CacheStorage {
    public function setTime($time);
    public function read($file);
    public function write($file, $data);
}
// Using Memcache
class Mcache extends Memcache implements CacheStorage {
    private $time = 86400;
    public function setTime($time) {
        $this->time = $time;
    }
    public function read($name) {
        return $this->get($name);
    }
    public function write($name, $data) {
        return $this->add($name, $data, MEMCACHE_COMPRESSED, $this->time);
    }
}
// Using Files System
class Fcache implements CacheStorage {
    private $dir;
    private $time = 86400;
    public function __construct($dir = "cache") {
        $this->setDir($dir);
    }
    public function setDir($dir) {
        $this->dir = $dir;
        if (! is_dir($this->dir) and ! mkdir($this->dir))
            throw new Exception("Invalid Directory");
        $this->dir = $dir;
    }
    public function setTime($time) {
        $this->time = $time;
    }
    public function read($name) {
        $name = $this->dir . "/" . $name;
        if (! is_file($name))
            return false;
        if (time() - filemtime($name) > $this->time)
            return false;
        $zd = gzopen($name, "r");
        $zr = "";
        while(! feof($zd)) {
            $zr .= gzread($zd, 1024);
        }
        gzclose($zd);
        return $zr;
    }
    public function write($name, $data) {
        $name = $this->dir . "/" . $name;
        touch($name);
        $gz = gzopen($name, "w9");
        gzwrite($gz, $data);
        gzclose($gz);
        return true;
    }
}

这个类会最小化和gz HTML输出

cleaner.php:

<?php  
class Cleaner{
  static function Clean($html){
      $html=preg_replace_callback("~<script(.*?)>(.*?)</script>~si",function($m){
         $m[2]=preg_replace("~//(.*?)'n~si"," ", " ".$m[2]." ");
         return "<script ".$m[1].">".$m[2]."</script>";
      }, $html);
      $search = array(
        "/ +/" => " ",
        "/<!–'{(.*?)'}–>|<!–(.*?)–>|['t'r'n]|<!–|–>|'/'/ <!–|'/'/ –>|<!'[CDATA'[|'/'/ ']']>|']']>|'/'/']']>|'/'/<!'[CDATA'[/" => "");
  //$html = preg_replace(array_keys($search), array_values($search), $html);   
  $search = array(
            "/'/'*(.*?)'*'/|['t'r'n]/s" => "",
            "/ +'{ +|'{ +| +'{/" => "{",
            "/ +'} +|'} +| +'}/" => "}",
            "/ +: +|: +| +:/" => ":",
            "/ +; +|; +| +;/" => ";",
            "/ +, +|, +| +,/" => ","
       );
       $html = preg_replace(array_keys($search), array_values($search), $html);
       preg_match_all('!(<(?:code|pre|script).*>[^<]+</(?:code|pre|script)>)!',$html,$pre);
       $html = preg_replace('!<(?:code|pre).*>[^<]+</(?:code|pre)>!', '#pre#', $html);
       $html = preg_replace('#<!–[^'[].+–>#', '', $html);
       $html = preg_replace('/['r'n't]+/', ' ', $html);
       $html = preg_replace('/>['s]+</', '><', $html);
       $html = preg_replace('/'s+/', ' ', $html);
       if (!empty($pre[0])) {
         foreach ($pre[0] as $tag) {
             $html = preg_replace('!#pre#!', $tag, $html,1);
         }
      }
      return($html);
  }
  static function Cleaning($html) {
         //put cache  checker here

     $html=self::Clean($html);//if you didn't want to minify commented this line
     if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')){
          $html= "'x1f'x8b'x08'x00'x00'x00'x00'x00".
          substr(gzcompress($html, 9), 0, - 4). // substr -4 isn't needed 
          pack('V', crc32($html)).   // crc32 and 
          pack('V', strlen($html));               // size are ignored by all the browsers i have tested 
          header("Content-Encoding: gzip");
          header('Content-Length: ' . strlen($html));
     }

        //you can save your cache 
      return($html);
 }
}?>

在PHP文件中的使用示例

 <?php require_once(dirname(__FILE__)."/cleaner.php"); 
 @ob_start(function($m){return Cleaner::Cleaning($m);});?>
 //begin of php file

//end of php file
<?php 
while (@ob_end_flush());?>