nginx 为什么浏览器不缓存PHP readfile()输出的文件?

mlnl4t2r  于 2023-08-03  发布在  Nginx
关注(0)|答案(3)|浏览(161)

我目前正在使用以下代码通过PHP的readfile()输出一些图像文件,但是,我注意到通过Firefox和Chrome的开发工具,这些文件都没有被缓存。

ob_start();
outputfile($fp);

function outputfile( $fp ) {

  header("Content-Type: $mime_type");
  header("Content-Length: " . filesize($fp));
  header("Cache-Control: public, max-age=3600");
  header("Etag: " . md5_file($fp));
  $date = gmdate("D, j M Y H:i:s", filemtime($fp))." GMT";
  header("Last-Modified: $date");

  readfile($fp);
  exit; // tried ob_end_flush() too before exiting

}

字符串
代码输出文件,在开发工具的头文件中包含以下内容...

Cache-Control: public, max-age=2678400
Connection: keep-alive
Content-Length: 155576
Content-Type: image/jpeg
Date: Mon, 21 May 2018 22:31:02 GMT
Last-Modified: Sat, 03 Mar 2018 19:34:05 GMT
Etag: 507f2520385c009a7385a1165032bd61
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Server: nginx


如果我将控制权返回给Nginx来提供文件,它会输出以下头:

Accept-Ranges: bytes
Connection: keep-alive
Content-Length: 155576
Content-Type: image/jpeg
Date: Mon, 21 May 2018 22:31:02 GMT
ETag: "5a9af8ad-4a5b"
Last-Modified: Sat, 03 Mar 2018 19:34:05 GMT
Server: nginx


我是否错过了导致浏览器不缓存图像文件的原因?
我已经尝试添加所有必要的缓存控制头,如eTag和max-age,但浏览器只是拒绝缓存数据。我甚至尝试从服务器的输出中复制所有的头文件,并使用“ob_start('ob_gzhandler');“以防是因为原始文件数据没有被Gzip压缩。
浏览器不会缓存任何通过PHP发送的文件数据。

tjjdgumg

tjjdgumg1#

我想我找到问题了...
想知道是否有任何cookie相关的代码可以影响readfile(),并发现如果我在使用该函数之前有session_start(),浏览器将拒绝缓存发送的文件数据。如果我删除session_start(),浏览器缓存会按照预期的方式工作,尊重发送的Cache-Control头。
我不太明白为什么会出现这种情况,因为我比较了readfile()的输出,在它之前有和没有session_start(),输出似乎是相同的。
我使用的是PHP 5.5。

am46iovg

am46iovg2#

Expires: Thu, 19 Nov 1981 08:52:00 GMT**可能是原因。从技术上讲,如果Cache-Control头部有一个max-age指令,那么Expires应该被忽略(参考:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires)的值。但是,值得通过删除该头来检查。
你的PHP代码没有设置它。所以我假设它来自一些常见的配置/代码,这些代码在每个传出的响应中执行。你有没有把这个放在你的Nginx配置中,用于所有的PHP请求?

ttp71kqs

ttp71kqs3#

我知道这是一个老问题。但我遇到了同样的问题,这给了我一个线索。我的最终解决方案是去掉PHP通常发送的所有头文件,然后用我自己的只与发送的文件相关的头文件替换它们。
我开始使用header_remove();你可能会发现你并不需要所有这些头文件,或者你可能需要其他头文件。但这些是我正在发送的,我得到了正确的缓存控制。
我发送缩略图图像,我建立在飞行或拉从我自己的缓存文件夹。

header_remove();
header('Cache-Control: max-age=' . Time::days(7));
header('content-disposition: inline; filename="thumb-' . $r["id"] . '-' . preg_replace('/\.[a-z]+$/', '.jpg', $r["name"]) . '"');
header('Last_Modified: ' . gmdate("D, d M Y H:i:s", strtotime($r["modified"])) . ' GMT');
header("expires: " . gmdate("D, d M Y H:i:s", time() + Time::days(7)) . " GMT");
header('etag: "' . $r["etag"] . '"');
header("accept-ranges: bytes");

字符串

相关问题