【问题标题】:304: Not modified and front end caching304:未修改和前端缓存
【发布时间】:2009-10-18 01:38:03
【问题描述】:

我正在使用 PHP 脚本来提供文件。 如果自客户端上次下载后文件未更改,我希望能够在我的 http 响应中发回 304 未修改的标头。这似乎是 Apache(和大多数其他 Web 服务器)中的一个功能,但我不知道如何通过 PHP 实现它。

我听说过使用$_SERVER['HTTP_IF_MODIFIED_SINCE'],但是这个变量似乎没有出现在我的$_SERVER 超级数组中。

我的问题不是如何返回 304 标头,而是如何知道应该返回一个。


编辑:问题是我的$_SERVER['HTTP_IF_MODIFIED_SINCE'] 没有设置。这是我的.htaccess 文件的内容:

ExpiresActive On 
ExpiresByType image/jpeg "modification plus 1 month"
ExpiresByType image/png "modification plus 1 month"
ExpiresByType image/gif "modification plus 1 month"
Header append Cache-Control: "must-revalidate" 


<IfModule mod_rewrite.c>
   RewriteEngine On
   RewriteCond $1 !^(controller\.php)
   RewriteRule (.*\.jpg|.*\.png|.*\.gif) controller.php/$1
</IfModule>

HTTP_IF_MODIFIED_SINCE 仍然没有出现在$_SERVER 超级数组中。

【问题讨论】:

    标签: php http caching http-headers


    【解决方案1】:

    HTTP_IF_MODIFIED_SINCE 是正确的做法。如果您没有得到它,请检查 Apache 是否启用了 mod_expiresmod_headers 并正常工作。借自a comment on PHP.net

    $last_modified_time = filemtime($file); 
    $etag = md5_file($file);
    // always send headers
    header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT"); 
    header("Etag: $etag"); 
    // exit if not modified
    if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time || 
        @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { 
        header("HTTP/1.1 304 Not Modified"); 
        exit; 
    }
    
    // output data
    

    【讨论】:

    • 我见过这种方式,但是 $_SERVER['HTTP_IF_MODIFIED_SINCE'] 对我来说总是空的......
    • 检查我最近的编辑——我遗漏了一段重要的 Apache 配置信息。
    • 尝试按照webmasterworld.com/forum23/2300.htm 修改我的 htaccess.txt 文件,但没有成功。有什么想法吗?
    • 没有 htaccess.txt 文件这样的东西。必须是 .htaccess 文件
    • 这个好答案的非常重要的部分是关于“Last-Modified”的“always send headers”。如果不发送此标头,您将永远不会在请求中获得 HTTP_IF_MODIFIED_SINCE,因为浏览器不会发送它。
    【解决方案2】:

    This article 将回答您关于缓存的所有问题

    我发现添加了

    RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}]
    RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
    

    到我的 htaccess 文件的底部(在所有 rewriterule 下方)工作。

    【讨论】:

      【解决方案3】:

      我遇到了这个问题,结果证明只是我打开了 Firebug。这在“网络”选项卡“禁用浏览器缓存”下有一个选项,默认勾选。 Chrome 的开发者工具中有一个类似的选项,菜单栏下方的栏上的复选框之一。

      取消勾选这些选项会导致浏览器正确发送HTTP_IF_MODIFIED_SINCE,并且一切正常(即使打开了 Firebug 或 Chrome 开发工具)。

      【讨论】:

        【解决方案4】:

        register_globals 关闭时,$_SERVER['HTTP_IF_MODIFIED_SINCE'] 通常为空。

        检查是否是这种情况,如果是,请尝试getenv('HTTP_IF_MODIFIED_SINCE')

        【讨论】:

          【解决方案5】:

          还有一些其他参数要检查..在我的情况下,我没有这两个标题:

          $_SERVER['HTTP_IF_NONE_MATCH'] && $_SERVER['HTTP_IF_MODIFIED_SINCE']
          

          需要返回正确的 304 标头,因为我的系统时钟有点晚,它会将这些页面解释为将来到期,然后根本不发送这些值

          还要检查 apache 返回的标头,或者至少将其覆盖为更大的值

          Cache-Control: max-age=3600
          

          因为它不会发送以前的标题,如果

          Last-Modified previous sent header < ( NOW - 3600 )
          

          所以在我的例子中,我设置了这个非常方便的函数 function lastModified($file){ $x=filemtime($file); while($x>time())$x-=86000;}#reduce by one day if touched in future date $date=gmdate('D, j M Y H:i:s',$x).' GMT'; header('Cache-Control: max-age=86000',1); if($_SERVER['HTTP_IF_NONE_MATCH'] == $x || $_SERVER['HTTP_IF_MODIFIED_SINCE']==$date){ header('HTTP/1.1 304 Not Modified',1,304);die;} header('Etag: '.$x,1);header('Last-Modified: '.$date,1); }

          【讨论】:

            【解决方案6】:

            请注意,$_SERVER["HTTP_IF_NONE_MATCH"] 可以包含引号和 -gzip 后缀。

            $server_etag = str_replace("-gzip", "", str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])));
            
            if ($server_etag == $etag) ...
            

            【讨论】:

              猜你喜欢
              • 2013-10-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-01-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-11-17
              相关资源
              最近更新 更多