如何让浏览器caching图片,用PHP?

我是如何caching图像全新的。

我用php输出图库中的所有图像,并希望已经显示的图像被浏览器caching,所以php脚本不必再输出相同的图像。 我想要的是图像显示更快。

当调用图像我喜欢这样:

<img src="showImage.php?id=601"> 

showImage.php文件做:

 $resultat = mysql_query(" SELECT filename, id FROM Media WHERE id = '".$_GET['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']."")); } 

如果您在输出消息之前使用php来检查用户是否已login,那么您不希望浏览器caching图像。

整个caching的重点是调用服务器一次,然后再不调用它。 如果浏览器caching图像,则不会调用服务器,脚本也不会运行。 相反,即使用户不再login,浏览器也会将您的映像从caching中取出并显示出来。这可能是一个非常大的安全漏洞。

首先,如果您使用会话,则必须禁用session_cache_limiter (将其设置为nonepublic )。 它发送的头对caching来说相当糟糕。

 session_cache_limiter('none'); 

然后发送Cache-Control: max-age= number_of_seconds并可select等效的Expires:标头。

 header('Cache-control: max-age='.(60*60*24*365)); header('Expires: '.gmdate(DATE_RFC1123,time()+60*60*24*365)); 

为了获得最佳的caching能力,如果浏览器发送匹配的If-Modified-Since标题,则发送Last-Modified标题并回复状态304和空的主体。

 header('Last-Modified: '.gmdate(DATE_RFC1123,filemtime($path_to_image))); 

为了简洁起见,我在这里作弊了一些(这个例子没有validationdate),但只要你不介意浏览器永远保留caching的文件,它就是有效的:

 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { header('HTTP/1.1 304 Not Modified'); die(); } 

以下是我用于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 MYH: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; } 

您可以将生成的图像存储在名为“showImage”的目录中,以便像这样embedded它们

 <img src="showimage/601.jpg" /> 

然后,将一个.htaccess文件放在与调用showImage.php?id =相同的目录下,以防文件不存在,例如:

 <IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)\.jpg$ showImage.php?id=$1 [QSA,L] </IfModule> 

只要阅读你的评论,你想做客户端caching:只需设置caching相关的HTTP头根据http://www.mnot.net/cache_docs/


请注意,您的查询容易受到SQL注入 ,因为您不清理/转义$ _GET ['id']: http : //php.net/mysql_real_escape_string

请不要地址图片是一些id'ed资源。 使用绝对的网站的图像,最好在一个子域,最好是cookiesless。 浏览器将对图像执行caching。 在网站上加载图像的一个巧妙的技巧是把它放在一些CDN或其他网站上。 这是因为浏览器将并行请求线程的数量限制为一个域。

处理图像的另一种方式是灵活的,查看它。 它节省了大量的带宽和请求。

如果速度如此重要,您也可以使用直接的位图加载。 虽然这不是build议大图像。 如果它的图标和小图像/你正在加载的gif。 您可以直接在页面上使用位图。