如何让浏览器缓存图片,用 PHP?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1385964/
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
How to get the browser to cache images, with PHP?
提问by Johan
I'm totally new to how to cache images.
我对如何缓存图像完全陌生。
I output all images in a gallery with PHP, and want the images already shown, to be cached by the browser, so the PHP script don't have to output the same image again. All I want is the images to show up faster.
我使用 PHP 输出图库中的所有图像,并希望已显示的图像由浏览器缓存,因此 PHP 脚本不必再次输出相同的图像。我想要的只是图像显示得更快。
When calling an image I do like this:
调用图像时,我喜欢这样:
<img src="showImage.php?id=601">
and the showImage.php-file does:
并且showImage.php-file 执行以下操作:
$id = (int) $_GET['id'];
$resultat = mysql_query("
SELECT filename, id
FROM Media
WHERE id = $id
");
$data = mysql_fetch_assoc($resultat);
...
//Only if the user are logged in
if(isset($_SESSION['user'])){
header("Content-Type: image/jpeg");
//$data['filename'] can be = dsSGKLMsgKkD3325J.jpg
echo(file_get_contents("images/".$data['filename'].""));
}
采纳答案by Imagist
If you are using php to check if the user is logged in before outputting the message, then you don't want the browser to cache the image.
如果您在输出消息之前使用 php 来检查用户是否已登录,那么您不希望浏览器缓存图像。
The entire point of caching is to call the server once and then never call it again. If the browser caches the image, it won't call the server and your script won't run. Instead, the browser will pull your image from cache and display it, even if the user is no longer logged in. This could potentially be a very big security hole.
缓存的全部意义在于调用服务器一次,然后再也不调用它。如果浏览器缓存图像,它不会调用服务器并且您的脚本不会运行。相反,即使用户不再登录,浏览器也会从缓存中提取您的图像并显示它。这可能是一个非常大的安全漏洞。
回答by Kornel
First of all, if you're using sessions, you must disable session_cache_limiter(by setting it to noneor public). Headers it sends are pretty bad for caches.
首先,如果您使用会话,则必须禁用session_cache_limiter(通过将其设置为none或public)。它发送的标头对缓存来说非常糟糕。
session_cache_limiter('none');
Then send Cache-Control: max-age=number_of_secondsand optionally an equivalent Expires:header.
然后发送Cache-Control: max-age=number_of_seconds和可选的等效Expires:标头。
header('Cache-control: max-age='.(60*60*24*365));
header('Expires: '.gmdate(DATE_RFC1123,time()+60*60*24*365));
For the best cacheability, send Last-Modifiedheader and reply with status 304 and empty body if the browser sends a matching If-Modified-Sinceheader.
为了获得最佳的可缓存性,Last-Modified如果浏览器发送匹配的If-Modified-Since标头,则发送标头并使用状态 304 和空正文进行回复。
header('Last-Modified: '.gmdate(DATE_RFC1123,filemtime($path_to_image)));
For brevity I'm cheating here a bit (the example doesn't verify the date), but it's valid as long as you don't mind browsers keeping the cached file forever:
为简洁起见,我在这里有点作弊(该示例不验证日期),但只要您不介意浏览器永远保留缓存文件,它就有效:
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header('HTTP/1.1 304 Not Modified');
die();
}
回答by KiNgMaR
Here's some code I use for 304 header support:
这是我用于 304 标头支持的一些代码:
/**
* @return false if not cached or modified, true otherwise.
* @param bool check_request set this to true if you want to check the client's request headers and "return" 304 if it makes sense. will only output the cache response headers otherwise.
**/
protected function sendHTTPCacheHeaders($cache_file_name, $check_request = false)
{
$mtime = @filemtime($cache_file_name);
if($mtime > 0)
{
$gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
$etag = sprintf('%08x-%08x', crc32($cache_file_name), $mtime);
header('ETag: "' . $etag . '"');
header('Last-Modified: ' . $gmt_mtime);
header('Cache-Control: private');
// we don't send an "Expires:" header to make clients/browsers use if-modified-since and/or if-none-match
if($check_request)
{
if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && !empty($_SERVER['HTTP_IF_NONE_MATCH']))
{
$tmp = explode(';', $_SERVER['HTTP_IF_NONE_MATCH']); // IE fix!
if(!empty($tmp[0]) && strtotime($tmp[0]) == strtotime($gmt_mtime))
{
header('HTTP/1.1 304 Not Modified');
return false;
}
}
if(isset($_SERVER['HTTP_IF_NONE_MATCH']))
{
if(str_replace(array('\"', '"'), '', $_SERVER['HTTP_IF_NONE_MATCH']) == $etag)
{
header('HTTP/1.1 304 Not Modified');
return false;
}
}
}
}
return true;
}
回答by middus
You could store the generated images in a directory called "showImage" so that you would embed them like this
您可以将生成的图像存储在名为“showImage”的目录中,以便像这样嵌入它们
<img src="showimage/601.jpg" />
Then you place a .htaccess filein the very same directory that will call showImage.php?id= in case the file does not exist, e.g.:
然后你将一个.htaccess 文件放在同一个目录中,如果文件不存在,它将调用 showImage.php?id= ,例如:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.jpg$ showImage.php?id= [QSA,L]
</IfModule>
Just read in your comment that you want to do client side caching: just set the caching-related HTTP headers according to http://www.mnot.net/cache_docs/
只需阅读您要进行客户端缓存的评论:只需根据http://www.mnot.net/cache_docs/设置与缓存相关的 HTTP 标头
回答by Ritesh M Nayak
Please do not address images are some id'ed resource. use absolute urls for images, preferably in a subdomain, preferably cookie less. The browser will do the caching on the images. A neat trick to load images faster on websites is to put it on some CDN or other site. This because browsers limit the number of parallel request threads to one domain.
请不要处理图片是一些 id'ed 资源。对图像使用绝对 url,最好在子域中,最好少 cookie。浏览器将对图像进行缓存。在网站上更快加载图像的一个巧妙技巧是将其放在某些 CDN 或其他网站上。这是因为浏览器将并行请求线程的数量限制为一个域。
Another neat way of working with images is spriting, look it up. It saves a lot of bandwidth and also requests.
另一种处理图像的巧妙方法是精灵,查找一下。它节省了大量带宽和请求。
You could also use direct bitmap loading if speed is so crucial. This is not advised for large images though. If its icons and small images/gifs that you are loading. You can use bitmaps directly on the page.
如果速度如此重要,您也可以使用直接位图加载。但是,不建议对大图像使用此方法。如果您正在加载它的图标和小图像/gif。您可以直接在页面上使用位图。

