一部の画像のキャッシュを無効にする


113

PHP libを使用していくつかの画像を生成します。

時々、ブラウザは新しく生成されたファイルをロードしません。

自分で動的に作成した画像のみのキャッシュを無効にするにはどうすればよいですか?

注:作成した画像には、同じ名前を使用する必要があります。

回答:


233

ハックのように感じられるがかなり移植性があるこの問題の一般的で単純な解決策は、ランダムに生成されたクエリ文字列を動的画像の各リクエストに追加することです。

したがって、たとえば-

<img src="image.png" />

なるだろう

<img src="image.png?dummy=8484744" />

または

<img src="image.png?dummy=371662" />

Webサーバーの観点からは同じファイルにアクセスしますが、ブラウザーの観点からはキャッシングを実行できません。

乱数の生成は、ページを提供するときにサーバーで(ページ自体がキャッシュされていないことを確認するだけです...)、またはクライアント(JavaScriptを使用)で発生します。

Webサーバーがこのトリックに対応できるかどうかを確認する必要があります。


87
乱数の代わりに、データが変更されたタイムスタンプまたは反映されたデータのバージョン番号を使用します。
lhunath


19
注意:実際にブラウザが画像をキャッシュするのを妨げるのではなく、キャッシュされた画像を見るのを防ぐだけです。適切なヘッダーを画像に適用することが、imhoの最良の方法です(以下のlhunathの解決策を参照)。この方法では、キャッシュしたくないイメージでキャッシュを不必要に埋めることもできるため、実際にキャッシュしたいもののキャッシュスペースを少なくするというコストがかかります。
ジョス2013年

この記事はそのような振る舞いの理由を説明していると思います。
Metalcoder、2013年

1
これは実際には機能しません。画像を別の方法でフラッシュする必要があります(通常、画像のトリミングでは、画像は同じままです)
Ben

44

ブラウザのキャッシュ戦略は、HTTPヘッダーによって制御できます。ほんのヒントにすぎないことを覚えておいてください。ブラウザーはこのフィールド(およびその他のフィールド)でひどく矛盾しているため、ブラウザーの範囲に望ましい効果を得るには、いくつかのヘッダーが必要になります。

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");

1
これはページ全体に適用されます... 1つの画像のみ(そのページの特定の画像)のキャッシュを無効にできませんか?
dole doug 2009

5
@Thorpe:HTTP応答に適用されます。応答に何が含まれているかは関係ありません。画像データ、HTMLデータ、その他何でもかまいません。うまくいかない場合は、おそらく正しく行われていません。応答のHTTPヘッダーをチェックして、正しく割り当てられているかどうかを確認してください。
lhunath 2009年

これがうまくいけばいいのに... Chromeには何の問題もありませんが、Firefox 14とIE 8は上記のヘッダーが送信されていても画像の更新を拒否します。これは、クエリ文字列に任意のパラメータを追加するよりもはるかにクリーンなソリューションでした。ため息
Pawel Krakowiak 2012

2
@PawelKrakowiakヘッダーを追加しても、すでにキャッシュされている画像では機能しないことに注意してください。これは、ブラウザがサーバーに問い合わせることもないため、ヘッダーが表示されないためです。それらはあなたがそれらを追加した後になされたどんな画像リクエストでも機能します。
lhunath 2016

2
このソリューションは、Webデザイナーではなくプログラマーを対象としています。それ自体がプログラミング言語で画像を生成していて、これがコメンターを混乱させるように思われない限り、画像を開いて画像にヘッダーを追加することはできないので、私は指摘したいと思いました。
Bruce、

12

JavaScriptを使用してブラウザーで動的に実行する必要がある場合、ここに例を示します...

<img id=graph alt="" 
  src="http://www.kitco.com/images/live/gold.gif" 
  />

<script language="javascript" type="text/javascript">
    var d = new Date(); 
    document.getElementById("graph").src = 
      "http://www.kitco.com/images/live/gold.gif?ver=" + 
       d.getTime();
</script>

12

ソリューション1は素晴らしいものではありません。それは機能しますが、画像ファイルの最後にランダムなまたはタイムスタンプ付きのハッキングクエリ文字列を追加すると、ページが読み込まれるたびに、画像が変化したかどうかに関係なく、ブラウザーがすべてのバージョンのすべてのバージョンを再ダウンロードしてキャッシュしますサーバー上。

ソリューション2は役に立たない。nocache画像ファイルにヘッダーを追加することは、実装が非常に難しいだけでなく、将来変更される可能性があると思われる画像を初めてロードするときに、事前いつ必要になるかを予測する必要があるため、完全に非現実的です。。

Etagsを入力してください...

絶対的な最善の方法私はこの問題を解決することが分かってきましたが使用することですのetagsを .htaccessファイル内のあなたのイメージディレクトリ内のファイル。次の例では、画像ファイルのヘッダーでブラウザーに一意のハッシュを送信するようにApacheに指示しています。このハッシュは、画像ファイルが変更されたときにのみ変更され、この変更により、次に画像が要求されたときにブラウザが画像を再読み込みします。

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>

11

私はすべての答えを確認しましたが、最良の答えはそうでした(そうではありません)。

<img src="image.png?cache=none">

最初は。

ただし、cache = noneパラメータ(静的な「none」という単語)を追加しても何も影響はなく、ブラウザはキャッシュからロードされます。

この問題の解決策は:

<img src="image.png?nocache=<?php echo time(); ?>">

基本的にUNIXタイムスタンプを追加してパラメーターを動的にし、キャッシュを作成しない場合、それは機能しました。

しかし、私の問題は少し異なりました:オンザフライで生成されたPHPチャート画像をロードし、$ _ GETパラメーターでページを制御していました。URLのGETパラメータが同じ場合はキャッシュから画像を読み取り、GETパラメータが変更された場合はキャッシュしないようにしたいと考えました。

この問題を解決するには、$ _ GETをハッシュする必要がありましたが、これが配列なので、解決策は次のとおりです。

$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";

編集

上記のソリューションは問題なく機能しますが、ファイルが変更されるまでキャッシュバージョンを提供したい場合があります。(上記のソリューションでは、そのイメージのキャッシュを完全に無効にします)したがって、イメージファイルの使用に変更が生じるまで、ブラウザからキャッシュされたイメージを提供するには、次のようにします。

echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";

filemtime()はファイル変更時刻を取得します。


4

このトピックは古いものですが、Googleで非常によくランク付けされています。これをヘッダーに入れるとうまくいくことがわかりました。

<meta Http-Equiv="Cache-Control" Content="no-cache">
<meta Http-Equiv="Pragma" Content="no-cache">
<meta Http-Equiv="Expires" Content="0">
<meta Http-Equiv="Pragma-directive: no-cache">
<meta Http-Equiv="Cache-directive: no-cache">

最近のブラウザーは残念ながらこれらのディレクティブを無視しているため、このソリューションは一部のブラウザーでのみ機能する可能性があります。また、特定のイメージだけでなく、すべてのキャッシュを無効にします
ZioCain

4

私はこれに対する解決策を探していただけで、上記の答えは私の場合うまくいきませんでした(そしてそれらについてコメントするのに十分な評判がありません)。少なくとも、私のユースケースと私が使用していたブラウザー(OSX上のChrome)では、キャッシュを妨げているように思われたのは、

Cache-Control = 'no-store'

完全を期すために、「no-cache、no-store、must-revalidate」の3つすべてを使用しています。

だから私の場合(PythonでFlaskから動的に生成された画像を提供する)、私はうまくいけばできるだけ多くのブラウザで動作するように次のことをしなければなりません...

def make_uncached_response(inFile):
    response = make_response(inFile)
    response.headers['Pragma-Directive'] = 'no-cache'
    response.headers['Cache-Directive'] = 'no-cache'
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    return response

応答にストアを置かないだけで十分に機能しました
scourge192

Chromeだけでなく、Firefoxにも対応しています。今では標準のようです:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control(「キャッシュの防止」セクションを参照)。
Gino Mempin

3

画像ソースを変更することが解決策です。画像にタイムスタンプまたは乱数を追加することで、実際にこれを行うことができます。

たとえば画像が表すデータのチェックサムを追加することをお勧めします。これにより、可能な場合はキャッシュが有効になります。


1

束に別のソリューション1を追加しましょう。

最後に一意の文字列を追加するのが最適なソリューションです。

example.jpg?646413154

以下のソリューションは、このメソッドを拡張し、キャッシング機能を提供し、イメージが更新されたときに新しいバージョンをフェッチします。

画像が更新されると、filemtimeが変更されます。

<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>

次に画像を出力します。

<img src="images/example.jpg?<?php echo $filemtime; ?>" >

1
これは、キャッシュの有効性のために使用したものです。
遺伝子

1

私はこの問題を抱えており、このように克服しています。

var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';

0

これを使用して同様の問題を解決しました...(外部プロバイダーからの)画像カウンターを表示します。常に正しく更新されませんでした。そして、ランダムなパラメータが追加された後、すべてうまくいきます:)

少なくとも1分ごとに更新されるように、日付文字列を追加しました。

サンプルコード(PHP):

$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";

その結果、次のsrcようなリンクになります。

http://xy.somecounter.com/?id=1234567890&1207241014

0

たとえば、http//example.com/image.jpgのようにハードコードされた画像URL がある場合、phpを使用して画像にヘッダーを追加できます。

まず、Apacheでjpgをphpとして処理する必要があります。ここを参照: PHPを拡張子file.php.jpgで実行することは可能ですか?

ファイル(imagecreatefromjpeg)をファイルからロードし、以前の回答のヘッダーを追加します。ヘッダーを追加するには、php関数ヘッダーを使用します。

次に、imagejpeg関数を使用して画像を出力します。

phpにjpg画像を処理させるのは非常に安全ではないことに注意してください。また、私がこのソリューションをテストしていないため、機能させるかどうかはあなた次第であることに注意してください。


-1

単純な、1つのヘッダーの場所を送信します。

私のサイトには1つの画像が含まれており、画像をアップロードした後、変更はありません。次のコードを追加します。

<?php header("Location: pagelocalimage.php"); ?>

仕事は私のためです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.