単純なブラウザキャッシュを利用するために、ユーザーの画像全体のファイル構造を変更する価値はありますか?


9

私のモバイルサイトの1つでは、ユーザーのプロフィール画像をユーザーフォルダーに「1.jpg」として保存し、そこから追加の写真をアップロードしていきます。つまり、たとえば、プロフィールの写真を変更しても、ファイル名は変わりません。

ユーザーのプロファイルが表示されて再表示されるたびに同じ古い写真が何度もダウンロードされないように、画像キャッシュを利用したいと思っていましたが、同時に、ユーザーのブラウザーに変更されている場合は、新しいものをダウンロードしてください。

私が読んでいることから、これを実際に行う唯一の方法は、実際にランダムなファイル名を使用し、DB内のそれらすべてのファイル名を追跡することです。これにより、有効期限のないキャッシュを設定できます。 -変更された写真は新しいファイル名を持っているため、再び取得されます。ただし、これまでに構造化した方法の優れている点は、データベースの場所を予測できるため、データベースを完全にスキップして、ファイルに直接アクセスできることです。

だから私の質問は、サイトのファイル構造全体を変更し、DB要素を追加して、永遠にキャッシュし、新しいアップロード時に自動的に再ダウンロードすることは価値があるのでしょうか?

これは大きな仕事ですが、それが価値があると思われる場合、私はこの劇的な変化を前進させることに問題はありません。これが「大物」のやり方であることを確認したいだけなので、ファイル構造を二度と変更する必要はありません。

ありがとう。

回答:


7

一般的に使用されるソリューションの1つは、画像のURLを次のようにすることです。

http://www.example.com/path/to/images/1.jpg?v=123456

これ/path/to/images/1.jpgは、画像の実際のURLパスです?v=123456が、URLの最後に追加されたダミーのクエリです。クエリ文字列は、バージョン番号、タイムスタンプ、画像コンテンツのハッシュなど、画像が変更されるたびに変更し、変更されない場合は変更しない限り、何でもかまいません。

トリックは、URLが実際には静的ファイルを指しているため、そのようなURLを提供するように要求された場合、Webサーバーはクエリ文字列を無視するということです。ただし、ユーザーのブラウザ(およびその間のプロキシ)にとっては、クエリ文字列が異なるURLは完全に異なるため、クエリ文字列を変更すると、ブラウザは強制的にファイルをリロードします。

したがって、WebサーバーExpiresCache-ControlHTTPヘッダーを送信するように構成して、HTTPヘッダーを無期限にキャッシュできるようにすることができます。これは、クエリ文字列を変更することでリロードを強制できるという知識で安全です。これを行う1つの方法は、Apacheでmod_expiresを使用している場合.htaccess、次の行を含むファイルを画像ディレクトリに配置することです。

ExpiresActive On
ExpiresDefault "access plus 1 year"

この手法は、多くの人気のあるWebサイトで使用されています。たとえば、このページのHTMLソースを見ると、そのスタイルシートが次のようなURLから読み込まれていることがわかります。

http://cdn.sstatic.net/stackoverflow/all.css?v=7cd8ea9d6f1e

ここで、これ?v=7cd8ea9d6f1eは上記で説明したのと同じダミーのクエリ文字列です。それを変更し、実際に同じファイルが返されることを確認することで確認できます。


また興味深いですが、ファイルを最後に変更した日時とブラウザが最初に表示された日時を追跡して、ユーザーのブラウザに再度フェッチするように指示するタイミングを決定するにはどうすればよいですか(たとえば、クエリ値を変更して)。
ProgrammerGirl

1
ファイルがいつ表示されたかを追跡する必要はありません。ファイルが最後に変更された日時(またはその他の適切なプロパティ)を追跡し、クエリ文字列に含めます。これにより、ファイルが変更されるたびにURLも変更されます。
Ilmari Karonen、2012

とても、とても、面白い。したがって、おそらくファイルの「最後に変更された」プロパティをフェッチし、そのクエリ値を正しくすることができますか?
ProgrammerGirl

1
はい、うまくいくはずです。
Ilmari Karonen

1
私が知っている重大な欠点はありません。検索エンジンのインデックスに画像のコピーが重複することになるかもしれませんが、少なくともGoogleなどの主要な検索エンジンは、そのような一般的なトリックであるため、そのようなことへの対処についてはかなり賢いです。いずれの場合でも、rel = "canonical" HTTPヘッダーを送信し、有効期限を控えめに(たとえば、1年ではなく1か月または1週間)維持することで、この問題を軽減できます。
Ilmari Karonen、2012

6

キャッシュする方法は複数あります。

条件付きGET

これらのイメージをファイルシステムに格納し、Webサーバー経由で直接提供する場合は、おそらくすでに条件付きgetを使用しています。ウェブサーバーは自動的にファイルシステムメタデータを使用してETAGヘッダーを設定し、ブラウザがリクエストにIf-Modified-SinceIf-Matchesヘッダーを含める場合は、「304 Not Modified」で自動的に応答します。(すべてのブラウザがします。)

この場合、イメージ全体が返されないため、帯域幅を節約できます。ただし、GETリクエストは引き続き発行されるため、リクエストのオーバーヘッドとレイテンシがあります。

ウェブサーバーにCache-Controlヘッダーにpublic,max-age=N画像の値を設定させることで、キャッシュの鮮度を犠牲にしてリクエスト数をわずかに減らすことができます。これは、キャッシュmax-ageが更新されているかどうかを確認する前に、キャッシュがリソースを最大で数秒間保持できることを示しています。

ただし、HTTPはキャッシュエントリを無効にする方法を1つしか定義していないため、アプリケーションのセマンティクスに適合しない可能性があります。プロフィール写真を更新するURLにPOSTまたはPUTすると、Location: [url of photo]ヘッダーで返信し、そのURLのキャッシュエントリは無効になります。

(これは、コメント付きのWebページをキャッシュし、ユーザーが新しいコメントを投稿した後、ブラウザがページを強制的に再読み込みできるようにするメカニズムです。ブラウザは、POST /commentwith 303 See Otherとに応答しLocation: /page/with/commentます。これは使用されていません。長期にわたるバグのため、Firefoxで動作します。)

大量のトラフィックがない限り、このキャッシュへのアプローチは問題ありません。

URLを変更する

URLはリソースの表現であるため、キャッシュを管理する別の方法は、リソースのキャッシュパラメータを変更するのではなく、「永久にキャッシュ」ディレクティブを使用して新しいリソースを作成することです。これは、「大物」が好むアプローチであり、余分な要求を生成せ、帯域幅を大幅に節約できるためです。欠点は、さらに多くの簿記が必要になることです。

これには2つの一般的な手法があります。

クエリ文字列

ファイルシステムからファイルを提供する場合、Webサーバーはクエリ文字列を無視します。:キャッシュは、しかし、ない/1.jpg?t=12345/1.jpg?t=67890、サーバーはそれらが同じであると思っていても、2つの完全に異なる、無関係な資源です。

したがって、HTML内のリソースを参照するときに、ファイルシステムのタイムスタンプをクエリ文字列として追加し、長いExpiresヘッダーを設定するのが簡単な方法です。ブラウザはない永遠にこのリソースをキャッシュしないであろう任意の長いクエリ文字列が変更されないようとして取得します。

欠点は、キャッシュを強制的に無効にしたい場合、アイテムの新しいURLをWebサーバーに指示することが困難または不可能であることです。たとえば、ブラウザに参照付きのキャッシュされたHTMLページがある/1.jpg?v=1が、たまたまエントリがクリアされた場合/1.jpg?v=1(ファイルまたはメモリ領域が足りなくなった可能性があります)、ブラウザはに新しいリクエストを送信し/1.jpg?v=1ます。その間に画像がに変わった/1.jpg?v=2場合、適切な応答は次のいずれかです。

  1. 古いバージョンのファイルを提供します。これは、特定の時点ですべてのリソースを互いに整合させたい場合に行います。これは、たとえば、古いhtmlファイルを含む新しいcssファイルが正しく機能しない可能性があるため、CSSファイルを使用して実行する必要があります。
  2. を使用して、ファイルの新しいバージョンにリダイレクトします301 Moved Permanently。すべてのリソースをできるだけ新しくしたい場合は、これを行います。

これらの両方をWebサーバーだけで行うのは困難です。つまり、画像要求に対してもWebアプリケーションを呼び出す必要があり、より複雑でリソースを大量に消費する可能性があります。ウェブサーバーはファイルを提供する速度非常に速いため、ウェブアプリケーションのオーバーヘッドによって、帯域幅とレイテンシが増加する可能性があります。

ファイル名

クエリ文字列を追加する代わりに、ファイル名を変更します。つまり、ファイルシステムにファイルの複数のバージョンを保持するのは簡単ですが、リソースとその名前を追跡するには、ファイルメタデータを保存し、他のデータベースブックキーピングを行う必要があるでしょう。


0

http statusについて読む304 Not Modifiedと、304でダウンロードリクエストに応答できるはずです。これにより、サーバーに、キャッシュされたデータを使用するように指示し、ブラウザに再送信するよう指示します。そして、この質問を読んでください


興味深いですが、これは問題のあるファイルスキーマに対する「バンドエイド」ソリューションですか、それとも私のファイルスキーマは優れていて、このキャッシング機能だけが必要ですか?また、ユーザーのブラウザーに再度フェッチするように指示するタイミングを判断するために、ファイルが最後に変更されたときとブラウザーが最初に表示されたときをどのようにして知ることができますか?
ProgrammerGirl

私はそれにあまり慣れていません。フランシスアビラはそれについてもっと知っていると思います
Puggan Se
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.