我对如何缓存图片完全不了解。
我使用PHP输出库中的所有图像,并希望浏览器缓存已显示的图像,因此PHP脚本不必再次输出相同的图像。我想要的只是图像显示得更快。
调用图像时,我喜欢这样:
<img src="showImage.php?id=601">
和showImage.php
- 文件确实:
$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'].""));
}
答案 0 :(得分:49)
首先,如果您正在使用会话,则必须停用session_cache_limiter
(将其设置为none
或public
)。它发送的标题对缓存来说非常糟糕。
session_cache_limiter('none');
然后发送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));
为了获得最佳的可缓存性,如果浏览器发送匹配的Last-Modified
标头,请发送If-Modified-Since
标头并回复状态304并清空。
header('Last-Modified: '.gmdate(DATE_RFC1123,filemtime($path_to_image)));
为了简洁,我在这里作弊(示例不验证日期),但只要您不介意浏览器永远保留缓存文件,它就是有效的:
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header('HTTP/1.1 304 Not Modified');
die();
}
答案 1 :(得分:7)
以下是我用于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;
}
答案 2 :(得分:5)
如果您在输出消息之前使用php检查用户是否已登录,那么您不希望浏览器缓存图像。
缓存的全部内容是调用服务器一次,然后再也不要再调用它。如果浏览器缓存图像,它将不会调用服务器,您的脚本将不会运行。相反,即使用户不再登录,浏览器也会从缓存中提取图像并显示它。这可能是一个非常大的安全漏洞。
答案 3 :(得分:4)
您可以将生成的图像存储在名为“showImage”的目录中,以便您可以像这样嵌入它们
<img src="showimage/601.jpg" />
然后将.htaccess file放在将调用showImage.php的同一目录中?id =如果文件不存在,例如:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)\.jpg$ showImage.php?id=$1 [QSA,L]
</IfModule>
只需在评论中读到您要进行客户端缓存:只需根据http://www.mnot.net/cache_docs/设置与缓存相关的HTTP标头
答案 4 :(得分:1)
请不要处理图像是一些id'ed资源。使用图像的绝对URL,最好是在子域中,最好是少于cookie。浏览器将对图像进行缓存。在网站上加载图像的一个巧妙方法就是把它放在一些CDN或其他网站上。这是因为浏览器将并行请求线程的数量限制为一个域。
另一种处理图像的简洁方法是精灵,查找它。它节省了大量带宽和请求。
如果速度如此重要,您还可以使用直接位图加载。但不建议使用大图像。如果它正在加载它的图标和小图像/ GIF。您可以直接在页面上使用位图。