我正在使用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
超级数组中。
答案 0 :(得分:26)
HTTP_IF_MODIFIED_SINCE
是正确的方法。如果您没有得到它,请检查Apache是否启用了mod_expires
和mod_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
答案 1 :(得分:1)
This article将回答有关缓存的所有问题
我发现添加了
RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}]
RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
在我的htaccess文件的底部(在所有rewriterule下面)工作。
答案 2 :(得分:0)
$_SERVER['HTTP_IF_MODIFIED_SINCE']
通常为空。
检查是否是这种情况,如果是,请尝试register_globals
答案 3 :(得分:0)
还有一些其他参数要检查..在我的情况下,我没有这两个标题:
$_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);
}
答案 4 :(得分:0)
我遇到了这个问题,结果只是我打开了Firebug。这在默认情况下勾选的网络选项卡“禁用浏览器缓存”下有一个选项。 Chrome的开发者工具中有一个类似的选项,菜单栏下栏上的一个勾选框。
取消这些选项会导致浏览器正确发送HTTP_IF_MODIFIED_SINCE
,一切正常(即使打开Firebug或Chrome开发工具)。
答案 5 :(得分:0)
请注意, $ _ SERVER [“ HTTP_IF_NONE_MATCH”] 可以包含引号和-gzip后缀。
$server_etag = str_replace("-gzip", "", str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])));
if ($server_etag == $etag) ...