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

时间:2018-05-21 22:58:15

标签: php nginx http-headers

我目前正在使用以下代码通过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

我是否遗漏了导致浏览器无法缓存图像文件的内容?

我尝试添加所有必要的Cache-Control标头,例如eTag和max-age,但浏览器只是拒绝缓存数据。我甚至尝试从服务器的输出中复制所有头文件并使用“ob_start('ob_gzhandler');”如果是因为原始文件数据没有被压缩。

浏览器不会缓存通过PHP发送的任何文件数据。

2 个答案:

答案 0 :(得分:0)

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请求?

答案 1 :(得分:0)

我想我发现了这个问题......

想知道任何与cookie相关的代码是否会影响readfile()并发现如果在使用该函数之前我有session_start(),浏览器将拒绝缓存发送的文件数据。如果我删除session_start(),浏览器缓存将按预期工作,并遵循发送的Cache-Control标头。

我不太明白为什么会出现这种情况,因为我在它之前比较了readfile()的输出和没有session_start(),输出似乎是相同的。

我记录的是使用PHP 5.5。