You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置PHP缓存头以避免浏览器发起不必要的请求

解决浏览器频繁发起缓存验证请求(304)的问题

要让浏览器在缓存有效期内完全不发起请求,核心是强制浏览器信任本地缓存,不触发任何条件验证,你的代码里有几个关键点需要调整:

问题分析

你当前设置了Last-Modified和Etag头,这两个头会让浏览器在缓存有效期内仍可能发起条件请求(比如用户手动刷新页面、浏览器默认策略触发验证),服务器返回304就是这种条件请求的响应。同时缺少immutable属性,无法明确告诉浏览器资源不会变更。

修改方案

  1. 更新Cache-Control头:添加immutable属性,明确告知浏览器在max-age有效期内,资源不会发生任何变化,无需发起验证请求;同时保留max-age设置缓存时长。
  2. 移除Last-Modified和Etag头:这两个头是触发条件请求的根源,删除后浏览器不会发送If-Modified-Since或If-None-Match请求头。
  3. 删除304响应处理逻辑:既然浏览器不会发起条件请求,这部分代码就不再需要。

修改后的代码:

$location = base64_decode($_GET['location']);
$path = path($location);

header('X-Sendfile: ' . $path);
header('Content-type: ' . mime_content_type($path));
header('Content-Disposition: inline; filename="' . basename($path) . '"');

// 调整Cache-Control,添加immutable属性
header('Cache-Control: private, max-age=' . 60 * 60 * 24 . ', immutable');
// 保留Expires作为兼容旧浏览器的 fallback
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 60 * 60 * 24) . ' GMT');

// 移除Last-Modified和Etag头
// header('Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', filemtime($path)));
// header('Etag: "' . md5_file($path) . '"');

// 删除304响应处理逻辑
// if ((isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= filemtime($path)) ||
//     (isset($_SERVER['HTTP_IF_NONE_MATCH']) && trim($_SERVER['HTTP_IF_NONE_MATCH']) === $etag)
// ) {
//     header('HTTP/1.1 304');
//     exit();
// }

readfile($path);

补充说明

  • immutable属性支持所有现代浏览器(Chrome、Firefox、Edge等),旧浏览器会忽略这个属性,仍可能发起条件请求,但这是兼容权衡。
  • 如果资源未来可能会更新,建议设置更长的max-age(比如30天),同时使用文件名哈希(比如image_v1.jpg)来强制浏览器获取新资源,而不是依赖缓存验证。
  • 测试时要确保浏览器没有开启"禁用缓存"的调试模式,否则所有设置都会被忽略。

内容的提问来源于stack exchange,提问作者Rick007110

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 08:55:57