apache 通过 PHP 缓存图像请求 - If-Modified-Since 未发送
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1038638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Caching image requests through PHP - If-Modified-Since not being sent
提问by Louis W
I am serving images through php and having some problems setting it up to respond with 304 headers to save on load time.
我正在通过 php 提供图像,但在设置它以响应 304 标头以节省加载时间时遇到了一些问题。
Most of the code below I found on php.net. It works, however ALWAYS responds with 200. For some reason the If-Modified-Since header is not being received on any requests even though I am sending the Last-Modified header initially.This is being done on an apache server. Any idea what might be wrong?
下面的大部分代码是我在 php.net 上找到的。它有效,但是总是以 200 响应。由于某种原因,即使我最初发送的是 Last-Modified 标头,也没有在任何请求中收到 If-Modified-Since 标头。这是在 apache 服务器上完成的。知道可能有什么问题吗?
This page will load the image from disk and display it to browser, along with sending a Last-Modified header. If you refresh the page, the browser doesn't send a If-Modified-Since header like it should.
此页面将从磁盘加载图像并将其显示到浏览器,同时发送一个 Last-Modified 标头。如果您刷新页面,浏览器不会像它应该发送的那样发送 If-Modified-Since 标头。
define('SITEPATH', (dirname($_SERVER['SCRIPT_NAME']) == '/') ? '/' : dirname($_SERVER['SCRIPT_NAME']).'/');
$load_path = $_SERVER['DOCUMENT_ROOT'] . SITEPATH . 'fpo_image.jpg';
// Get headers sent by the client.
$headers = apache_request_headers();
$file_time = filemtime($load_path);
header('Cache-Control: must-revalidate');
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $file_time).' GMT');
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $file_time)) {
header('HTTP/1.1 304 Not Modified');
header('Connection: close');
} else {
header('HTTP/1.1 200 OK');
header('Content-Length: '. filesize($load_path));
header('Content-type: image/jpeg');
readfile($load_path);
}
采纳答案by anveo
I believe it should be
我相信应该是
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) >= $file_time)) {
Checking if the modified time is greater than or equal rather than just equal. Although I do understand the two values shouldbe the same.
检查修改时间是否大于或等于而不是仅仅等于。虽然我确实理解这两个值应该是相同的。
回答by Keith Hughitt
mandor at mandor dot netposted a solutionat the PHP.net documentation for the header function which worked for me:
mandor at mandor dot net在 PHP.net 文档中发布了一个对我有用的头函数的解决方案:
<?php
// Test image.
$fn = '/test/foo.png';
// Getting headers sent by the client.
$headers = apache_request_headers();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
header('Content-Length: '.filesize($fn));
header('Content-Type: image/png');
print file_get_contents($fn);
}
?>
回答by Zsolti
After searching for a while, I've found the answer. The browser didn't cached anything (and didn't send the If-Modified-Since) until I sent the following header:
经过一段时间的搜索,我找到了答案。浏览器没有缓存任何东西(也没有发送If-Modified-Since),直到我发送了以下标头:
Cache-Control: private;
After doing this all worked fine.
完成此操作后,一切正常。
回答by Satish Gadhave
I had to use Keith's solution with combination of azkotoki's and Zsolti's posts above to make everything work as required.
我不得不将 Keith 的解决方案与上面 azkotoki 和 Zsolti 的帖子结合使用,以使一切都按要求工作。
so, final example would be:
所以,最后一个例子是:
<?php
// Test image.
$fn = '/test/foo.png';
session_cache_limiter(false);
header('Cache-Control: private');
// Getting headers sent by the client.
$headers = apache_request_headers();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 304);
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate('D, d M Y H:i:s', filemtime($fn)).' GMT', true, 200);
header('Content-Length: '.filesize($fn));
header('Content-Type: image/png');
print file_get_contents($fn);
}
?>
回答by azkotoki
Check if sessions are being used on that page, If so, try this:
检查该页面上是否正在使用会话,如果是,请尝试以下操作:
session_cache_limiter(false);
If the above worked, here's the explanation:
如果上述方法有效,则解释如下:
Php's session mechanism sends some automatic cache-related headers in order to improve the session cookie privacy, avoiding it to be cached by intermediate proxyes:
Php 的 session 机制为了提高 session cookie 的隐私性,会自动发送一些缓存相关的 headers,避免被中间代理缓存:
http://php.net/manual/en/function.session-cache-limiter.php
http://php.net/manual/en/function.session-cache-limiter.php
These automatic headers cause the browser not to ever send the If-Modified-Since header, as they instruct it to not to perform any caching at all.
这些自动标头导致浏览器永远不会发送 If-Modified-Since 标头,因为它们指示它根本不执行任何缓存。

