简体   繁体   中英

How to gzip cached files using ob_

I'm looking for a way to gzip a cached copy of my html and also to server the cached version to users, is this possible? I have this so far...

// at the head

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

//at the footer

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

Any guidance will be much appreciated.

You don't need to compress each files enable Output Compression in php.ini and its done automatically

zlib.output_compression = On

Or start output buffer with

ob_start('ob_gzhandler');

Now if the Purpose of your cache is because of speed and storage space then don't use filesystem just use Memcached .. it support in built compression

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

Update

Here is a simple script to manage both file cache and memcache ... you can easly extend it to other types of storage such as mongoDB or redis

Using File System

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

Using Memcache

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

Your Script

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

As you can see $storage storage can be either file or memcache here is the class used

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);
    }
}

Storage

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;
    }
}

this class minify and gz html output

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);
 }
}?>

sample of use in your php file

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM