PHP动态文件缓存问题


PHP Dynamic Files Caching Problem

我有一些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中使用了自动gzip:

 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数据似乎搞砸了,可能是压缩的内容或类似的东西。Chrome网络控制台有时显示以下错误:"资源解释为其他,但传输MIME类型未定义"。Mozilla有时会对index.php发出2次请求,或者尝试使用下载提示来下载它。有时文件请求停在5,而我通常加载7个文件,最后下载的文件内容混乱,如:

���������ÿÿ���������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
....

会是什么呢?

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

我在php手册页上发现了这条注释,这可能是你遇到的。

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

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