深入PHP与浏览器缓存的分析

我们往往在服务器上对缓存设置进行各种优化方案,但是我们却很少注意到客户端缓存,准确的说是浏览器的缓存机制。
其实每种浏览器都有缓存策略,会暂时将每一个浏览过的文件缓存在一个特殊的文件夹里。我们就可以在用户重复提交页面请求的时候,告诉用户这个页 面没有改变,可以调用缓存。 那我们怎么知道用户有没有这个页面的缓存数据呢? 其实浏览器在发送请求的时候会先发送http头,一般象这样:
Date: Sun, 30 Jul 2006 09:18:11 GMT
Content-Type: image/gif
Last-Modified: Wed, 19 Jul 2006 07:40:06 GMT
ETag: "8c55da8d6abc61:2327"
Content-Length: 14757
其中
Last-Modified: Wed, 19 Jul 2006 07:40:06 GMT
ETag: "8c55da8d6abc61:2327"
就是有关页面的缓存信息的。然后如果服务器返回的响应代码不是HTTP 200 (OK),而是 304的话,浏览器就会从缓存中读取数据。
//告诉客户端浏览器不使用缓存,HTTP 1.1 协议 
header("Cache-Control: no-cache, must-revalidate");

//告诉客户端浏览器不使用缓存,兼容HTTP 1.0 协议 
header("Pragma: no-cache"); 
根据这个原理,可以用在不经常更新或者需要经常刷新的页面,可以大大减轻服务器的负担,因为它如果发现客户端有缓存,就向客户端发送一个304响应,然后停止程序的执行。

浏览器发出的请求中包含If-Modified-Since和If-None-Match 两个参数,第一个表示询问数据的最后修改时间是否是Thu,19 Jun 2008 16:24:01 GMT 然后服务器就会检查数据的最后修改时间,如果是该时间则返回状态码304(表示没有修改),此时当浏览器收到状态码是304时就不会下载数据而是从本地缓 存中调用。然而只有本地缓存中存在着该请求资源的数据时浏览器才会发送If-Modified-Since参数并且其值为上一次服务器所返回的Last- Modified的值(并不是所有的服务器都支持If-Modified-Since和If-None-Match );If-None-Match的功能也类似,它是由服务器返回的Etag的值生成的,可以是任意值,因为其作用仅仅是使服务器检查数据的修改时间然后返 回而已,只要不为none(默认值)或不为空其它的都可以。

所以我们可以在代码的最前部分设置返回给浏览的Etag为某个值,然后在这个资源被第二次请求的时候就会附带着一个If-None-Match 参 数,通过核实其值确实为所发出的Etag值时就可以指定服务器返回为304然后强行退出程序就行了,If-Modified-Since也是一样的做法这 里就只给出etag方法的php版(Last-Modified版的太常见了如设置缓存超时等等):
PHP 代码复制到剪贴板


代码如下:

if ($_SERVER["HTTP_IF_NONE_MATCH"] == "claymorephp.com")
    {
        header('Etag:'.'zhaiyun.com',true,304);
        exit();
    }
    else {
        header('Etag:'."claymorephp.com");
    }
    你还可以稍微改一下:
    $expires=date("Ymd"); //一天后缓存过期
    if ($_SERVER["HTTP_IF_NONE_MATCH"] == $expires)
    {
        header('Etag:'.$expires,true,304);
        exit();
    }
    else {
        header('Etag:'.$expires);
    }
if ($_SERVER["HTTP_IF_NONE_MATCH"] == "claymorephp.com") { header('Etag:'.'zhaiyun.com',true,304); exit(); } else { header('Etag:'."claymorephp.com"); } 你还可以稍微改一下: $expires=date("Ymd"); //一天后缓存过期 if ($_SERVER["HTTP_IF_NONE_MATCH"] == $expires) { header('Etag:'.$expires,true,304); exit(); } else { header('Etag:'.$expires); }

另外,当GZIP和ETAG同时使用时有时会出问题,就是ETAG没有值,这个问题是普遍存在的,我暂时没有找到相关的原因,网上搜了一会,普遍的人称之为BUG。
基于以上原因,关于PHPBLOG的客户端缓存是以下来处理的(同时对HTTP_IF_NONE_MATCH和HTTP_IF_MODIFIED_SINCE进行判断):
PHP 代码复制到剪贴板


代码如下:

if($_SERVER['HTTP_IF_NONE_MATCH'])
        {
            if($_SERVER['HTTP_IF_NONE_MATCH'] == 'phpblog')
            {
                header('Etag:phpblog',true,304);//控制浏览器缓存
                $_SESSION['time_end']=microtime(true);
                exit();
            }
        }
        else if($_SERVER['HTTP_IF_MODIFIED_SINCE'])//eg:Sun, 02 Nov 2008 07:08:25 GMT; length=35849
        {
            $array=explode(' ',$_SERVER['HTTP_IF_MODIFIED_SINCE']);
            $gmday=$array[1];
            $month_array=array(
            "Jan"=>"01",
            "Feb"=>"02",
            "Mar"=>"03",
            "Apr"=>"04",
            "May"=>"05",
            "Jun"=>"06",
            "Jul"=>"07",
            "Aug"=>"08",
            "Sep"=>"09",
            "Oct"=>"10",
            "Nov"=>"11",
            "Dec"=>"12");
            $gmmonth=$month_array[$array[2]];
            $gmyear=$array[3];
            $array=explode(':',$array[4]);
            $gmtimestamp=gmmktime($array[0],$array[1],$array[2],$gmmonth,$gmday,$gmyear);
            if(gmmktime()-$gmtimestamp<$config_client_cache_time*60*60)
            {
                header('Etag:phpblog',true,304);//控制浏览器缓存
                $_SESSION['time_end']=microtime(true);
                exit();
            }
        }
if($_SERVER['HTTP_IF_NONE_MATCH']) { if($_SERVER['HTTP_IF_NONE_MATCH'] == 'phpblog') { header('Etag:phpblog',true,304);//控制浏览器缓存 $_SESSION['time_end']=microtime(true); exit(); } } else if($_SERVER['HTTP_IF_MODIFIED_SINCE'])//eg:Sun, 02 Nov 2008 07:08:25 GMT; length=35849 { $array=explode(' ',$_SERVER['HTTP_IF_MODIFIED_SINCE']); $gmday=$array[1]; $month_array=array( "Jan"=>"01", "Feb"=>"02", "Mar"=>"03", "Apr"=>"04", "May"=>"05", "Jun"=>"06", "Jul"=>"07", "Aug"=>"08", "Sep"=>"09", "Oct"=>"10", "Nov"=>"11", "Dec"=>"12"); $gmmonth=$month_array[$array[2]]; $gmyear=$array[3]; $array=explode(':',$array[4]); $gmtimestamp=gmmktime($array[0],$array[1],$array[2],$gmmonth,$gmday,$gmyear); if(gmmktime()-$gmtimestamp<$config_client_cache_time*60*60) { header('Etag:phpblog',true,304);//控制浏览器缓存 $_SESSION['time_end']=microtime(true); exit(); } }

缓存的HEADER是这样来发送的:
PHP 代码复制到剪贴板


代码如下:

$client_cache_time=$config_client_cache_time*60*60;//单位 - 秒
            header('Cache-Control: public, max-age='.$client_cache_time);
            header('Expires: '.gmdate('D, d M Y H:i:s',time()+$client_cache_time).' GMT');//设置页面缓存时间
            header('Last-Modified: '.gmdate('D, d M Y H:i:s',time()).' GMT');//返回最后修改时间
            header('Pragma: public');
            header('Etag:phpblog');//返回标识,用于标识上次的确访问过(浏览器中存在缓存)
$client_cache_time=$config_client_cache_time*60*60;//单位 - 秒 header('Cache-Control: public, max-age='.$client_cache_time); header('Expires: '.gmdate('D, d M Y H:i:s',time()+$client_cache_time).' GMT');//设置页面缓存时间 header('Last-Modified: '.gmdate('D, d M Y H:i:s',time()).' GMT');//返回最后修改时间 header('Pragma: public'); header('Etag:phpblog');//返回标识,用于标识上次的确访问过(浏览器中存在缓存)

(0)

相关推荐

  • php禁止直接从浏览器输入地址访问.php文件的方法

    本文实例讲述了php禁止直接从浏览器输入地址访问.php文件的方法.分享给大家供大家参考.具体实现方法如下: 一般来说对于有些重要的文件我们并不希望用户可以直接输入地址进行访问,对此我们需要进行一些设置.下面总结了一些php禁止直接从浏览器输入地址访问.PHP文件方法,非常实用. 比如说http://www.jb51.net/xx.php 这个文件我不想让别人直接从浏览器输入地址访问. 但是如果从任何网站连接http://www.jb51.net/xx.php过来不可以访问的话,本机建立连接也无

  • 控制PHP的输出:缓存并压缩动态页面

    mod_gzip是一个Apache模块,其功能是使用Gzip压缩静态的html页面,遵循IETF标准的浏览器可以接受gzip编码(IE, Netscape等).mod_gzip可以将页面的下载时间提高4-5倍.我强烈建议你在你的web服务器上使用mod_gzip.然而,我们还必须用PHP建立我们自己的压缩引擎.在这篇文章里,我将要介绍如何使用PHP的输出控制函数来大幅加速页面载入速度. 介绍PHP的输出控制函数 PHP4中最令人满意的事是--你可以让PHP缓存所有由脚本生成的输出,在你决定把它们

  • php强制文件下载而非在浏览器打开的自定义函数分享

    有时我们希望如图片.文本文档.网页.mp3.pdf等内容,当点击对应链接时直接下载,而不是在网页上显示,那么就需要强制设置header头信息.以下为一段不会产生乱码的php函数实现代码,其他程序语言也可参考之编写实现. 复制代码 代码如下: /** * Downloader * * @param $archivo *  path al archivo * @param $downloadfilename *  (null|string) el nombre que queres usar par

  • php 禁止页面缓存输出

    复制代码 代码如下: <?php header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT'); header('Cache-Control: no-cache, must-revalidate'); header('Pragma: no-cache'); ?>

  • PHP禁止页面缓存的代码

    核心代码: 复制代码 代码如下: header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT"); header("Cache-Control: no-cache, must-revalidate"); header("Pramga: no-cac

  • 使用php判断浏览器的类型和语言的函数代码

    我们经常看到有一些网站上面会显示出你目前使用的浏览器类型和使用的语言,比如显示的是:您使用的浏览器为 IE6,繁体字.看起来是不是很炫. 其实这样的功能不难实现,无非就是判断浏览器的类型和语言,如果用JS来做应该很简单,这里我们看看用PHP来怎么实现这样的功能,既然是在做判断,就可以用PHP的条件语句if..else来判断实现. 判断浏览器类型: <?php echo $_SERVER["HTTP_USER_AGENT"]; ?> 判断浏览器语言: <?php ech

  • php导出csv数据在浏览器中输出提供下载或保存到文件的示例

    1.在浏览器输出提供下载 复制代码 代码如下: /** * 导出数据到CSV文件 * @param array $data  数据 * @param array $title_arr 标题 * @param string $file_name CSV文件名 */function export_csv(&$data, $title_arr, $file_name = '') {    ini_set("max_execution_time", "3600");

  • php页面缓存ob系列函数介绍

    这里有缓存技术的简单介绍:http://www.jb51.net/article/4965.htm php页面缓存主要用到的是ob系列函数,如ob_start(),ob_end_flush(),ob_get_contents() 下面是编码部分. 1.初始化函数,一般是设置页面缓存路径.缓存文件命名格式等,可按个人喜好自定义.这里用到的识别ID是经加密的$_SERVER[REQUEST_URI]参数.这个函数中最后还有一个if判断:若未过缓存期,则加载缓存文件,否则加载源文件. 复制代码 代码如

  • php禁止浏览器使用缓存页面的方法

    本文实例讲述了php禁止浏览器使用缓存页面的方法.分享给大家供大家参考.具体方法如下: 页面缓存在有的时候是不需要的,我们可以禁止浏览器缓存页面. 在PHP中可以轻松的使用下面的语句实现禁止页面缓存,但比较难记特整理下,方便大家使用. php代码如下: 复制代码 代码如下: <?php // 设置此页面的过期时间(用格林威治时间表示),只要是已经过去的日期即可. header ( " Expires: Mon, 26 Jul 1970 05:00:00 GMT " );  //

  • PHP下利用header()函数设置浏览器缓存的代码

    这涉及到4种头标类型: Last-Modified(最后修改时间); Expires(有效期限); Pragma(编译指示): Cache-Control(缓存控制); 前三个头标属于HTTP1.0标准.头标Last-Modified使用UTC日期时间值.如果缓存系统发现Last-Modified值比页面缓存版本的更接 近当前时间,他就知道应该使用来自服务器的新版本. Expires 表明了缓存版本何时应该过期(格林威治标准时间).把它设置为一个以前的时间就会强制使用服务器上的页面. Pragm

  • 兼容ie6浏览器的php下载文件代码分享

    PS:这段代码在win系统下跑没有问题,枫哥亲测可用.如果用的是linux或是其他系统,要要诸位自行测试下啦. $filename = "./".$_REQUEST['name']; //这里是枫哥具体路径,只要$filename是所要下载文件的完整路径就可以. if (!is_file($filename)) {//检测文件是否存在. die('下载的文件好像跟TM谁私奔啦!'); } $filepath = str_replace('\\', '/', realpath($file

  • PHP实现根据浏览器跳转不同语言页面代码

    复制代码 代码如下: <?php$lan = $_SERVER['HTTP_ACCEPT_LANGUAGE'];   //获取浏览器语言版本if (preg_match("/[zh]{2}\-[hk]{2}/", $lan) || preg_match("/[zh]{2}\-[tw]{2}/", $lan)) {//台湾香港转到繁体页面     $url = 'hk/index.php';    header("location: " .

  • PHP限制页面只能在微信自带浏览器访问的代码

    为了防止自己辛辛苦苦做的webapp被人copy,我们都想限制程序只能在微信里面浏览,虽然下面实现了这个功能,单都是小菜,没什么技术含量,懂代码的伪造下就破了.下面是PHP限制页面只能在微信自带浏览器访问的代码. 复制代码 代码如下: <!--?php <br ?--> $useragent = $_SERVER['HTTP_USER_AGENT']; if (strpos($useragent, 'MicroMessenger') === false) { echo " 非微

随机推荐