程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> PHP設置圖片浏覽器緩存方法介紹

PHP設置圖片浏覽器緩存方法介紹

編輯:關於PHP編程

不管你是使用php打開浏覽器緩存還是使用apache,iis服務器環境來配置我們都是會針對浏覽器的Cache-Control來操作,下面我來給大家介紹PHP設置圖片浏覽器緩存

Cache-Control

Cache-Control 是最重要的規則。這個字段用於指定所有緩存機制在整個請求/響應鏈中必須服從的指令。這些指令指定用於阻止緩存對請求或響應造成不利干擾的行為。這些指令通常覆蓋默認緩存算法。緩存指令是單向的,即請求中存在一個指令並不意味著響應中將存在同一個指令。

cache-control 定義是:Cache-Control = “Cache-Control” “:” cache-directive。表 1 展示了適用的值。

表 1. 常用 cache-directive 值
Cache-directive 說明 public 所有內容都將被緩存 private 內容只緩存到私有緩存中 no-cache 所有內容都不會被緩存 no-store 所有內容都不會被緩存到緩存或 Internet 臨時文件中 must-revalidation/proxy-revalidation 如果緩存的內容失效,請求必須發送到服務器/代理以進行重新驗證 max-age=xxx (xxx is numeric) 緩存的內容將在 xxx 秒後失效, 這個選項只在HTTP 1.1可用, 並如果和Last-Modified一起使用時, 優先級較高

在客戶端通過浏覽器發出第一次請求某一個URL時,根據 HTTP 協議的規定,浏覽器會向服務器傳送報頭(Http Request Header),服務器端響應同時記錄相關屬性標記(Http Reponse Header),服務器端的返回狀態會是200,格式類似如下:

 代碼如下 復制代碼

HTTP/1.1 200 OK
Date: Tue, 03 Mar 2009 04:58:40 GMT
Content-Type: image/jpeg
Content-Length: 83185
Last-Modified: Tue, 24 Feb 2009 08:01:04 GMT
Cache-Control: max-age=2592000
Expires: Thu, 02 Apr 2009 05:14:08 GMT
Etag: “5d8c72a5edda8d6a:3239″


客戶端第二次請求此URL時,根據 HTTP 協議的規定,浏覽器會向服務器傳送報頭(Http Request Header),服務器端響應並記錄相關記錄屬性標記文件沒有發生改動,服務器端返回304,直接從緩存中讀取:

 代碼如下 復制代碼

HTTP/1.x 304 Not Modified
Date: Tue, 03 Mar 2009 05:03:56 GMT
Content-Type: image/jpeg
Content-Length: 83185
Last-Modified: Tue, 24 Feb 2009 08:01:04 GMT
Cache-Control: max-age=2592000
Expires: Thu, 02 Apr 2009 05:14:08 GMT
Etag: “5d8c72a5edda8d6a:3239″


一、Last-Modified、Expires和Etag相關工作原理
1、Last-Modified
在浏覽器第一次請求某一個URL時,服務器端的返回狀態會是200,內容是你請求的資源,同時有一個Last-Modified的屬性標記(Http Reponse Header)此文件在服務期端最後被修改的時間,格式類似這樣:

1 Last-Modified: Tue, 24 Feb 2009 08:01:04 GMT
客戶端第二次請求此URL時,根據 HTTP 協議的規定,浏覽器會向服務器傳送 If-Modified-Since 報頭(Http Request Header),詢問該時間之後文件是否有被修改過:

1 If-Modified-Since: Tue, 24 Feb 2009 08:01:04 GMT
如 果服務器端的資源沒有變化,則自動返回 HTTP 304 (Not Changed.)狀態碼,內容為空,這樣就節省了傳輸數據量。當服務器端代碼發生改變或者重啟服務器時,則重新發出資源,返回和第一次請求時類似。從而 保證不向客戶端重復發出資源,也保證當服務器有變化時,客戶端能夠得到最新的資源。

注:如果If-Modified-Since的時間比服務器當前時間(當前的請求時間request_time)還晚,會認為是個非法請求

2、Etag工作原理

HTTP 協議規格說明定義ETag為“被請求變量的實體標記” (參見14.19)。

簡單點即服務器響應時給請求URL標記,並在HTTP響應頭中將其傳送到客戶端,類似服務器端返回的格式:

1 Etag: “5d8c72a5edda8d6a:3239″
客戶端的查詢更新格式是這樣的:

1 If-None-Match: “5d8c72a5edda8d6a:3239″
如果ETag沒改變,則返回狀態304。
即:在客戶端發出請求後,Http Reponse Header中包含 Etag: “5d8c72a5edda8d6a:3239″
標識,等於告訴Client端,你拿到的這個的資源有表示ID:5d8c72a5edda8d6a:3239。

當下次需要發Request索要同一個URI的時候,浏覽器同時發出一個If-None-Match報頭( Http Request Header)此時包頭中信息包含上次訪問得到的Etag: “5d8c72a5edda8d6a:3239″標識。

1 If-None-Match: “5d8c72a5edda8d6a:3239″
這樣,Client端等於Cache了兩份,服務器端就會比對2者的etag。如果If-None-Match為False,不返回200,返回304 (Not Modified) Response。

3、Expires
給出的日期/時間後,被響應認為是過時。如Expires: Thu, 02 Apr 2009 05:14:08 GMT
需和Last-Modified結合使用。用於控制請求文件的有效時間,當請求數據在有效期內時客戶端浏覽器從緩存請求數據而不是服務器端. 當緩存中數據失效或過期,才決定從服務器更新數據。

4、Last-Modified和Expires
Last-Modified標識能夠節省一點帶寬,但是還是逃不掉發一個HTTP請求出去,而且要和Expires一起用。而Expires標識卻使得浏 覽器干脆連HTTP請求都不用發,比如當用戶F5或者點擊Refresh按鈕的時候就算對於有Expires的URI,一樣也會發一個HTTP請求出去, 所以,Last-Modified還是要用的,而 且要和Expires一起用。

5、Etag和Expires
如果服務器端同時設置了Etag和Expires時,Etag原理同樣,即與Last-Modified/Etag對應的Http Request Header:If-Modified-Since和If-None-Match。我們可以看到這兩個Header的值和Web Server發出的Last-Modified,Etag值完全一樣;在完全匹配If-Modified-Since和If-None-Match即檢查 完修改時間和Etag之後,服務器才能返回304.

6、Last-Modified和Etag
Last-Modified 和ETags請求的http報頭一起使用,服務器首先產生 Last-Modified/Etag標記,服務器可在稍後使用它來判斷頁面是否已經被修改,來決定文件是否繼續緩存

過程如下:
1. 客戶端請求一個頁面(A)。
2. 服務器返回頁面A,並在給A加上一個Last-Modified/ETag。
3. 客戶端展現該頁面,並將頁面連同Last-Modified/ETag一起緩存。
4. 客戶再次請求頁面A,並將上次請求時服務器返回的Last-Modified/ETag一起傳遞給服務器。
5. 服務器檢查該Last-Modified或ETag,並判斷出該頁面自上次客戶端請求之後還未被修改,直接返回響應304和一個空的響應體。

注:
1、Last-Modified和Etag頭都是由Web Server發出的Http Reponse Header,Web Server應該同時支持這兩種頭。
2、Web Server發送完Last-Modified/Etag頭給客戶端後,客戶端會緩存這些頭;
3、客戶端再次發起相同頁面的請求時,將分別發送與Last-Modified/Etag對應的Http Request Header:If-Modified-Since和If-None-Match。我們可以看到這兩個Header的值和Web Server發出的Last-Modified,Etag值完全一樣;
4、通過上述值到服務器端檢查,判斷文件是否繼續緩存;

二、對於非實時交互動態頁面中Epires和Etag處理
對數據更新並不頻繁、如tag分類歸檔等等,可以考慮對其cache。簡單點就是在非實時交互的動態程序中輸出expires和etag標識,讓其緩存。 但需要注意關閉session,防止http response時http header包含session id標識;

3.1、Expires
如expires.php

 代碼如下 復制代碼

header(’Cache-Control: max-age=86400,must-revalidate’);
header(’Last-Modified: ‘ .gmdate(’D, d M Y H:i:s’) . ‘ GMT’ );
header(”Expires: ” .gmdate (’D, d M Y H:i:s’, time() + ‘86400′ ). ‘ GMT’);


3.2、Etag
根據Http返回狀態來處理。當返回304直接從緩存中讀取
如etag.php

 代碼如下 復制代碼

cache();
echo date(”Y-m-d H:i:s”);
function cache()
{
       $etag = “http://longrujun.name”;
       if (isset($_SERVER['HTTP_IF_NONE_MATCH'])  &&
$_SERVER['HTTP_IF_NONE_MATCH'] == $etag)
       {
              header(’Etag:’.$etag,true,304);
              exit;
       }
       else header(’Etag:’.$etag);
}

圖片緩存實例

 代碼如下 復制代碼


$imagePath = "path/to/some/image";
 
$eTag = $imagePath;
$eTag .= fileMTime($imagePath);
$eTag = md5($eTag);
 
if((isset($_SERVER['HTTP_IF_NONE_MATCH'])) &&
(stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == $eTag)) {
    header("HTTP/1.1 304 Not Modified", TRUE, 304);
    exit();
}
 
header("ETag: ".$eTag);
header("Content-Type: image/png");
readFile($imagePath);
exit();

上面的方法超級簡單,下面看個完整實例

 代碼如下 復制代碼

$fullpath = '/www/images/' . basename($_GET['img']); //假定文件都在/www/images/下
if (!is_file($fullpath)) {
    header("HTTP/1.0 404 Not Found");
    exit();
}
 
$info = getImageSize($fullpath); //獲取圖片信息
if (!$info) {                    //如果不是圖片
    header("HTTP/1.0 404 Not Found");
    exit();
}
 
// 以下凡是header函數都是在輸出頭部信息。較多。
header('Content-type: '. $info['mime']);          //類似於image/png
header('Content-Length: '. filesize($fullpath));  //文件長度
 
header('Pragma: ');             //沒用,但要設置,防止服務器生成no-cache的可怕字眼
 
//手動設置過期時間,單位都是秒
$validtime = 48* 60 * 60;    // 48小時
 
//緩存相對請求的時間,
header('Cache-Control: ' . 'max-age='. $validtime);
 
//也很重要的Expires頭,功能類似於max-age
//time()+$validtime: 設置期限,到期後才會向服務器提交請求
//gmdate,生成Sun, 01 Mar 2009 04:05:49 +0000  的字符串,而且是GMT標准時區
//preg_replace,  生成Sun, 01 Mar 2009 04:05:49 GMT, 注意:可能與服務器設置有關,
//但我都用默認設置
header('Expires:'. preg_replace('/.{5}$/', 'GMT', gmdate('r', time()+ $validtime)));
 
//文件最後修改時間
$lasttime = filemtime($fullpath);
 
//最後修改時間,設置了,點擊刷新時,浏覽器再次請求圖片才會發出'IF_MODIFIED_SINCE'頭,
//從而被php程序讀取
header('Last-Modified: ' . preg_replace('/.{5}$/', 'GMT', gmdate('r', $lasttime) ));
 
//重要,如果請求中的時間和 文件生成時間戳相等,則文件未修改,客戶端可用緩存
if (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lasttime) {
    header("HTTP/1.1 304 Not Modified"); //服務器發出文件不曾修改的指令
    exit();
}
 
//如果文件被修改了,只好重新發出數據
echo file_get_contents($fullpath);

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved