在尝试进一步缩小问题范围时,我找到了问题的原因。我使用的是由 Apache 重写的 URL(即,我总是访问http://foo.com/page
由 Apache 映射到的我的页面http://foo.com/page.htm
)。只要我指定正确的 HTTP 标头( , 等),使用真实的 URL 就可以解决问题并使IE7满意。Cache-Control
Expires
这是我在 PHP 代码中所做的输出标头的操作,这似乎使所有浏览器都对缓存感到满意:
function emitConditionalGet($timestamp)
{
// See also http://www.mnot.net/cache_docs/
// and code sample http://simonwillison.net/2003/Apr/23/conditionalGet/
$gmdate_exp = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
$last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
$etag = '"'.md5($last_modified).'"';
// If the client provided any of the if-modified-since or if-none-match
// infos, take them into account:
$if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
$if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH'])
? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false;
if (!$if_modified_since && !$if_none_match)
{
return; // the client does not cache anything
}
if ($if_none_match && $if_none_match != $etag)
{
return; // ETag mismatch: the page changed!
}
if ($if_modified_since && $if_modified_since != $last_modified)
{
return; // if-modified-since mismatch: the page changed!
}
// Nothing changed since last time client visited this page.
header("HTTP/1.0 304 Not Modified");
header("Last-Modified: $last_modified");
header("ETag: $etag");
header("Cache-Control: private, max-age=1, must-revalidate");
header("Expires: $gmdate_exp");
header("Pragma: private, cache");
header("Content-Type: text/html; charset=utf-8");
exit;
}
function emitDefaultHeaders($timestamp)
{
$gmdate_exp = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
$last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
$etag = '"'.md5($last_modified).'"';
header("Last-Modified: $last_modified");
header("ETag: $etag");
header("Cache-Control: private, max-age=1, must-revalidate");
header("Expires: $gmdate_exp");
header("Pragma: private, cache");
header("Content-Type: text/html; charset=utf-8");
}
function getTimestamp()
{
// Find out when this page's contents last changed; in a static system,
// this would be the file time of the backing HTML/PHP page. Add your
// own logic here:
return filemtime($SCRIPT_FILENAME);
}
// ...
$timestamp = getTimestamp();
emitConditionalGet($timestamp);
emitDefaultHeaders($timestamp); //previously, this variable was mistyped as "$timestaml"