136

バックグラウンド

私は、2 つのプロボノ Web サイト用に、非常に単純な CGI ベース (Perl) のコンテンツ管理ツールを作成して使用しています。Web サイトの管理者にイベント用の HTML フォームを提供し、フィールド (日付、場所、タイトル、説明、リンクなど) を入力して保存します。そのフォームで、管理者がイベントに関連する画像をアップロードできるようにします。フォームを表示している HTML ページでは、アップロードされた画像のプレビューも表示しています (HTML img タグ)。

問題

問題は、管理者が画像を変更したい場合に発生します。彼は「参照」ボタンを押して新しい写真を選び、OK を押すだけでした。そして、これはうまくいきます。

画像がアップロードされると、バックエンドの CGI がアップロードを処理し、フォームを適切にリロードします。

問題は、表示されている画像が更新されないことです。データベースに正しい画像が保持されていても、古い画像が引き続き表示されます。イメージが Web ブラウザーにキャッシュされているという事実に絞り込みました。管理者が Firefox/Explorer/Safari で RELOAD ボタンを押すと、すべてが正常に更新され、新しい画像が表示されます。

私の解決策 - 機能しない

非常に過去の日付で HTTP Expires 命令を記述して、キャッシュを制御しようとしています。

Expires: Mon, 15 Sep 2003 1:00:00 GMT

私は管理者側にいることを思い出してください。ページは常に期限切れになっているため、ページの読み込みに少し時間がかかるかどうかはあまり気にしません.

しかし、これもうまくいきません。

ノート

画像をアップロードするとき、そのファイル名はデータベースに保持されません。これは、Image.jpg という名前に変更されます(使用時に単純化するため)。既存の画像を新しいものに置き換える場合、名前も変更されません。画像ファイルの内容が変わるだけです。

Web サーバーは、ホスティング サービス/ISP によって提供されます。アパッチを使用しています。

質問

Web ブラウザに、このページの内容 (画像でさえも) を強制的にキャッシュさせないようにする方法はありますか?

データベースで実際に「ファイル名を保存する」オプションを調整しています。このように、画像が変更されると、IMG タグの src も変更されます。ただし、これにはサイト全体で多くの変更が必要であり、より良い解決策がある場合は変更しません。また、アップロードされた新しい画像が同じ名前の場合、これはまだ機能しません (画像が少しフォトショップされて再アップロードされたとします)。

4

19 に答える 19

206

Armin Ronacher は正しい考えを持っています。問題は、ランダムな文字列が衝突する可能性があることです。私は使うだろう:

<img src="picture.jpg?1222259157.415" alt="">

「1222259157.415」はサーバーの現在の時刻です。
Javascriptperformance.now()または Python で時間を生成するtime.time()

于 2008-09-24T12:27:06.420 に答える
47

簡単な修正: ランダムなクエリ文字列を画像に添付します。

<img src="foo.cgi?random=323527528432525.24234" alt="">

HTTP RFC の内容:

Cache-Control: no-cache

しかし、それはうまくいきません:)

于 2008-09-24T12:20:36.000 に答える
26

PHP の file modified time functionを使用します。次に例を示します。

echo <img  src='Images/image.png?" . filemtime('Images/image.png') . "'  />";

画像を変更すると、変更されたタイムスタンプが異なるため、キャッシュされた画像ではなく新しい画像が使用されます。

于 2012-09-17T04:04:44.613 に答える
7

画像を提供するためのプロキシ スクリプトを作成することもできますが、これは少し手間がかかります。このようなもの:

HTML:

<img src="image.php?img=imageFile.jpg&some-random-number-262376" />

脚本:

// PHP
if( isset( $_GET['img'] ) && is_file( IMG_PATH . $_GET['img'] ) ) {

  // read contents
  $f = open( IMG_PATH . $_GET['img'] );
  $img = $f.read();
  $f.close();

  // no-cache headers - complete set
  // these copied from [php.net/header][1], tested myself - works
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Some time in the past
  header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 
  header("Cache-Control: no-store, no-cache, must-revalidate"); 
  header("Cache-Control: post-check=0, pre-check=0", false); 
  header("Pragma: no-cache"); 

  // image related headers
  header('Accept-Ranges: bytes');
  header('Content-Length: '.strlen( $img )); // How many bytes we're going to send
  header('Content-Type: image/jpeg'); // or image/png etc

  // actual image
  echo $img;
  exit();
}

実際には、イメージ src のキャッシュなしヘッダーまたは乱数で十分なはずですが、防弾にしたいので..

于 2008-09-24T12:48:51.203 に答える
5

私は新しいコーダーですが、ブラウザーがキャッシュしてウェブカメラのビューを保持するのを防ぐために、私が思いついたのは次のとおりです。

<meta Http-Equiv="Cache" content="no-cache">
<meta Http-Equiv="Pragma-Control" content="no-cache">
<meta Http-Equiv="Cache-directive" Content="no-cache">
<meta Http-Equiv="Pragma-directive" Content="no-cache">
<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">

どのブラウザーで何が機能するかはわかりませんが、一部のブラウザーでは機能します: IE: Web ページが更新されたとき、および Web サイトが (更新なしで) 再度アクセスされたときに機能します。CHROME: Web ページが更新された場合にのみ機能します (再訪問した後でも)。SAFARI と iPad: 動作しません。履歴と Web データを消去する必要があります。

SAFARI/iPad に関するアイデアはありますか?

于 2016-03-31T16:40:05.427 に答える
4

画像をアップロードするとき、そのファイル名はデータベースに保持されません。これは、Image.jpgという名前に変更されています(単に使用するときにわかりやすくするため)。

これを変更すると、問題が修正されます。上記で提案したソリューションと同様に、タイムスタンプを使用します。Image- <timestamp> .jpg

おそらく、画像のファイル名を同じに保つことで回避している問題はすべて克服できますが、それらが何であるかはわかりません。

于 2008-09-25T02:09:45.007 に答える
2

私の観点からは、画像のキャッシュを無効にすることは悪い考えです。まったく。

ここでの根本的な問題は、サーバー側で画像が更新されたときに、ブラウザに強制的に画像を更新させる方法です。

繰り返しますが、私の個人的な観点から言えば、最善の解決策は画像への直接アクセスを無効にすることです。代わりに、サーバー側のフィルター/サーブレット/その他の同様のツール/サービスを介して画像にアクセスします。

私の場合、画像を返し、それに応じて ETag を添付するのは残りのサービスです。サービスはすべてのファイルのハッシュを保持し、ファイルが変更されるとハッシュが更新されます。最新のすべてのブラウザで完全に機能します。はい、実装には時間がかかりますが、それだけの価値があります。

唯一の例外はファビコンです。何らかの理由で、機能しません。ブラウザにサーバー側からキャッシュを強制的に更新させることができませんでした。ETags、Cache Control、Expires、Pragma ヘッダー、何も役に立ちませんでした。

この場合、ランダム/バージョン パラメータを URL に追加することが唯一の解決策のようです。

于 2015-11-25T11:50:53.317 に答える
2

問題は、Expires:ヘッダーにもかかわらず、ブラウザがキャッシュをチェックするのではなく、更新前の画像のメモリ内コピーを再利用していることです。

ストアのようなサイトの管理者バックエンドで製品画像をアップロードする非常によく似た状況がありました。私の場合、他の人の URL 変更技術を使用せずに、javascript を使用して画像を強制的に更新することが最善の選択肢であると判断しました。ここですでに言及しました。代わりに、画像の URL を非表示の IFRAME に入れ、location.reload(true)IFRAME のウィンドウで呼び出し、ページ上の画像を置き換えました。これにより、現在表示しているページだけでなく、後でアクセスするページでも画像が強制的に更新されます。クライアントまたはサーバーは、URL クエリ文字列またはフラグメント識別子パラメーターを覚えておく必要はありません。

これを行うためのコードを回答hereに投稿しました。

于 2014-03-15T21:30:17.953 に答える
1

元の質問は、テキスト情報とともに保存された画像に関するものだと思います。したがって、src=... url を生成するときにテキスト コンテキストにアクセスできる場合は、無意味なランダムまたはタイム スタンプの代わりに、イメージ バイトの CRC32 を格納/使用することを検討してください。すると、画像がたくさんあるページが表示されていれば、更新された画像だけがリロードされます。最終的に、CRC の保存が不可能な場合は、実行時に計算して URL に追加できます。

于 2010-02-21T15:32:19.887 に答える
1

あなたとクライアントの間で動作の悪い透過プロキシが存在する可能性があるため、画像がキャッシュされないことを完全に保証する唯一の方法は、クエリ文字列として、または道。

そのタイムスタンプがイメージの最終更新時間に対応している場合、必要なときにキャッシュして、適切なタイミングで新しいイメージを提供できます。

于 2008-09-24T12:24:02.933 に答える
-1

すべての画像とリンクにタイムスタンプを自動的に追加する PHP スクリプトを作成しました。このスクリプトをページに含めるだけです。楽しみ!

http://alv90.altervista.org/how-to-force-the-browser-not-to-cache-images/

于 2019-12-30T14:28:55.253 に答える