PHP动态文件缓存问题

时间:2011-09-16 21:30:13

标签: php apache .htaccess caching http-headers

我有一些CSS和JS文件,由PHP在我的.htaccess中使用它动态生成:

AddHandler application/x-httpd-php .css .js

然后在文件中,例如:

<?PHP if ($Browser == 'msie') { ?>
.bind('selectstart', function(event) { [...] })
<?PHP } ?>

在它们的顶部(第一行),我使用基于Last-Modified标头的条件get,如下所示:

<?PHP if (FileIsCached(getlastmod())) die(); ?>

这是功能:

public static function FileIsCached($Timestamp)
{
    $LastModified = substr(date('r', $Timestamp), 0, -5).'GMT';
    $IfModifiedSince = (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false);

    if (($Semicolon = strrpos($IfModifiedSince, ';')) !== false)
        $IfModifiedSince = substr($IfModifiedSince, 0, $Semicolon);

    header('Last-Modified: '.$LastModified);

    if (!$IfModifiedSince || ($IfModifiedSince != $LastModified))
        return false;

    header('HTTP/1.1 304 Not Modified');

    return true;
}

我不需要检查编码,因为我在php.ini中使用自动gzipping:

 output_handler = ob_gzhandler

我把它们放在我的index.php里面就像这样:

<script type="<?PHP echo $JavascriptMIME; ?>" src="/script.js"></script>

一切都像魅力......这是我的第一个负载响应标题:

HTTP/1.1 200 OK
Date: Fri, 16 Sep 2011 21:21:51 GMT
Last-Modified: Fri, 16 Sep 2011 19:25:37 GMT
Content-Encoding: gzip
Vary: Accept-Encoding
Cache-Control: max-age=31536000, public
Expires: Sat, 15 Sep 2012 21:21:51 GMT
Content-Type: application/javascript
Content-Length: 6161
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive

这是我的缓存响应标头:

HTTP/1.1 304 Not Modified
Date: Fri, 16 Sep 2011 21:24:39 GMT
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
Expires: Sat, 15 Sep 2012 21:24:39 GMT
Cache-Control: max-age=31536000, public
Vary: Accept-Encoding

问题在于,有时HTTP数据似乎搞砸了,可能是通过gzip压缩内容或类似内容。 Chrome网络控制台有时会显示以下错误:“资源解释为其他,但传输的MIME类型未定义”。 Mozilla有时会对index.php发出2次请求,或者尝试使用下载提示下载它。有时文件请求在我正常加载7个文件时停止在5,并且最后下载的文件内容混乱如下:

���������ÿÿ���������HTTP/1.1 200 OK
Date: Fri, 16 Sep 2011 19:53:26 GMT
Server: Apache/2.2.17 (Win32) PHP/5.3.6
X-Powered-By: PHP/5.3.6
Cache-Control: must-revalidate, no-cache, no-store, private, public
Cache-Control: max-age=0, max-stale=0, post-check=0, pre-check=0
Expires: Wed, 11 Apr 1984 18:36:00 GMT
Expires: 0
Last-Modified: Fri, 16 Sep 2011 19:53:26 GMT
Pragma: no-cache
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Type: application/javascript
Content-Length: 674
Keep-Alive: timeout=5, max=99
Connection: Keep-Alive
....

它有什么用?

1 个答案:

答案 0 :(得分:0)

尝试在PHP中关闭输出处理程序,看看是否正常工作。

我在php手册页上找到了this comment,这可能是你遇到的。

你可以尝试一下,如果是问题,可以使用Apache的SetOutputFilter通过将以下内容添加到httpd.conf而不是让PHP执行来为你gzip内容

<Location />
# Insert filter
SetOutputFilter DEFLATE

# Netscape 4.x has some problems...
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08 have some more problems
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE masquerades as Netscape, but it is fine
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# NOTE: Due to a bug in mod_setenvif up to Apache 2.0.48
# the above regex won't work. You can use the following
# workaround to get the desired effect:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# Don't compress images
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary

# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary
</Location>