web-dev-qa-db-ja.com

PHPでブラウザに画像をキャッシュさせる方法は?

画像をキャッシュする方法はまったく新しいです。

PHPを使用してギャラリー内のすべての画像を出力し、既に表示されている画像をブラウザーでキャッシュしたいので、PHPスクリプトで同じ画像を再度出力する必要はありません。すべてIより速く表示するための画像です。

画像を呼び出すとき、私は次のようにします:

<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']."")); 
}
24
Johan

メッセージを出力する前にユーザーがログインしているかどうかを確認するためにphpを使用している場合、ブラウザに画像をキャッシュさせたくないでしょう。

キャッシングの全体的なポイントは、サーバーを一度呼び出した後、二度と呼び出さないことです。ブラウザが画像をキャッシュする場合、サーバーを呼び出さず、スクリプトは実行されません。代わりに、ユーザーがログインしていない場合でも、ブラウザーは画像をキャッシュからプルして表示します。これは、非常に大きなセキュリティホールになる可能性があります。

5
Imagist

まず、セッションを使用している場合は、 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();
}
49
Kornel

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;
  }
7
KiNgMaR

生成した画像を「showImage」というディレクトリに保存して、次のように埋め込むことができます。

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

次に、ファイルが存在しない場合にshowImage.php?id =を呼び出すディレクトリと同じディレクトリに 。htaccess file を配置します。例:

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

コメントでクライアント側のキャッシュを実行することを読んでください。キャッシュ関連のHTTPヘッダーを http://www.mnot.net/cache_docs/ に従って設定するだけです。

4
middus

画像が一部のid'edリソースであることに対処しないでください。画像には絶対URLを使用してください。できればサブドメインで使用し、できればCookieを少なくしてください。ブラウザは画像のキャッシュを行います。 Webサイトで画像をより速くロードするための巧妙なトリックは、CDNまたは他のサイトにそれを置くことです。これは、ブラウザーが並列要求スレッドの数を1つのドメインに制限するためです。

画像を操作するもう1つのきちんとした方法は、スプリットです。それは多くの帯域幅と要求を節約します。

速度が非常に重要な場合は、ビットマップを直接ロードすることもできます。ただし、大きな画像の場合はお勧めしません。あなたがロードしているそのアイコンと小さな画像/ gifの場合。ページ上でビットマップを直接使用できます。

1
Ritesh M Nayak