讓瀏覽器快取 PHP 產生的圖片

由於 stickeraction 的關係, 貼出去的貼紙讓我的主機流量暴增, 覺得這樣下去這個月的 100G 流量一定會爆, 所以對於貼出去的貼紙做了一些處理, 讓瀏覽器快取住, 多少可以減少一些流量, 其實一開始就該做了 XD 只是沒有意識到, 完全沒有經驗 XD 而且工作上也比較沒有流量的考量, 所以這次也學到了些東西。

原本在主機上就都有設定 lighttpd, 讓圖片, js 跟 css 檔產生 etag、expire 跟 last modified … 等的 HTTP headers, 利用瀏覽器的快取機制來減少主機的流量。 不過由 PHP 產生的圖片完全沒有 cache, 今天才改了一下程式, 加上一些 header, 來減少流量的支出, 不然這個月主機流量穩爆 ~"~

$file = 'foo.jpg'; $file_etag = fileinode($file); $file_mtime = gmstrftime("%a, %d %b %Y %T %Z", filemtime($file));<p>$header_etag = array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)?$_SERVER['HTTP_IF_NONE_MATCH']:false; $header_mtime = array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)?$_SERVER['HTTP_IF_MODIFIED_SINCE']:false;</p><p>if ($header_etag == '"'.$file_etag.'"' AND $header_mtime == $file_mtime) { header('HTTP/1.1 304 Not Modified'); } else { header("Content-Type: " . $content_type); header("Content-Length: " . filesize($file)); header("Last-Modified: " . $file_mtime); header('ETag: "'.$file_etag.'"'); readfile($file); }</p>

由於是輸出圖片, 所以 Content-Type 是一定要的, 然後還有 Content-Length, 比較重要的就是 Last-Modified 跟 ETag 這兩個 header 了, 送出這些 header 之後, 下次在瀏覽器在 request 同一張圖片時, 瀏覽器的 request header 就會送出 If-Modified-Since 跟 If-None-Match, 所以只要我們可以取得這兩個 header, 就可以判斷是否要在送出一次圖片, 如果這兩個 header 的數值都沒變, 那麼就可以告訴瀏覽器說不用在抓圖片了阿, 就丟個 304 Not Modified 的 header 回去就可以了, 就也不用再輸出圖片了。

由於我是用 lighttpd, 所以直接對 $SERVER 變數來存取 headers , 如果是用 apache 的話可以看看 apacherequest_headers 這個函式, 取得的變數名稱跟 header 一樣, 會比較直覺一點。

不過還有一些其他的 header, 像是 expire、max-age 跟 cache-control 這還要再研究一下 ~"~ 至少要可以控制哪時候過期嘛。

tzangms

Read more posts by this author.

Subscribe to Oceanic / 海海人生

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!