Lohnt es sich, die gesamte Dateistruktur meiner Benutzerbilder zu ändern, um das einfache Browser-Caching zu nutzen?

9

Auf einer meiner mobilen Websites speichere ich einfach die Profilbilder meiner Benutzer als "1.jpg" in ihrem Benutzerordner und gehe von dort aus schrittweise zu zusätzlichen Bildern, die sie hochladen. Dies bedeutet, dass der Dateiname bei jeder Änderung des Profilbilds beispielsweise gleich bleibt.

Ich wollte das Bild-Caching nutzen, damit das gleiche alte Bild nicht immer wieder heruntergeladen wird, wenn das Profil eines Benutzers angezeigt und erneut angezeigt wird, aber gleichzeitig möchte ich, dass die Browser meiner Benutzer dies tun Laden Sie das neue herunter, wenn es sich geändert hat.

Nach dem, was ich gelesen habe, scheint die einzige Möglichkeit, dies wirklich zu tun, darin zu bestehen, zufällige Dateinamen zu verwenden und alle diese Dateinamen in der Datenbank zu verfolgen, sodass Sie in letzter Zeit einen nicht ablaufenden Cache festlegen können -veränderte Bilder werden erneut gezogen, da sie einen neuen Dateinamen haben. Das Schöne an der Art und Weise, wie ich sie bisher strukturiert habe, ist jedoch, dass ich die Datenbank vollständig überspringen und direkt auf die Dateien zugreifen kann, da ihr Speicherort vorhersehbar ist.

Meine Frage ist also, ob es sich für mich lohnt, die gesamte Dateistruktur meiner Site zu ändern und das DB-Element hinzuzufügen, um das ewige Caching und das automatische erneute Herunterladen beim erneuten Hochladen zu gewährleisten.

Dies ist ein großes Unterfangen, aber wenn es als würdig erachtet wird, habe ich kein Problem damit, diese drastische Änderung voranzutreiben. Ich möchte nur sicherstellen, dass die "großen Jungs" das so machen, damit ich die Dateistruktur nie wieder ändern muss.

Vielen Dank.

ProgrammerGirl
quelle

Antworten:

7

Eine häufig verwendete Lösung besteht darin, Ihre Bild-URLs ungefähr so ​​aussehen zu lassen:

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

Hier /path/to/images/1.jpgist der tatsächliche URL-Pfad des Bildes, während ?v=123456nur eine Dummy-Abfrage am Ende der URL angezeigt wird. Die Abfragezeichenfolge kann beliebig sein - eine Versionsnummer, ein Zeitstempel, ein Hash des Bildinhalts -, solange Sie sie ändern, wenn sich das Bild ändert, und sie beibehalten, wenn dies nicht der Fall ist.

Der Trick besteht darin, dass der Webserver, wenn er aufgefordert wird, eine solche URL bereitzustellen, die Abfragezeichenfolge ignoriert, da die URL tatsächlich auf eine statische Datei verweist. Für den Browser des Benutzers (und für alle dazwischen liegenden Proxys) sind URLs mit unterschiedlichen Abfragezeichenfolgen jedoch völlig unterschiedlich. Daher zwingt jede Änderung der Abfragezeichenfolge den Browser, die Datei neu zu laden.

Auf diese Weise können Sie Ihren Webserver so konfigurieren, dass er Expiresund Cache-ControlHTTP-Header sendet , um ein unbegrenztes Caching zu ermöglichen. Dabei können Sie sicher sein, dass Sie ein erneutes Laden erzwingen können, indem Sie die Abfragezeichenfolge ändern. Wenn Sie Apache mit mod_expires verwenden , können Sie dies tun, indem Sie eine .htaccessDatei mit den folgenden Zeilen in Ihr Image-Verzeichnis einfügen :

ExpiresActive On
ExpiresDefault "access plus 1 year"

Diese Technik wird von vielen beliebten Websites verwendet. Wenn Sie sich beispielsweise die HTML-Quelle dieser Seite ansehen, werden Sie feststellen, dass das Stylesheet dafür von einer URL wie der folgenden geladen wird:

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

Hier ist das ?v=7cd8ea9d6f1eeine Dummy-Abfragezeichenfolge, wie ich sie oben beschrieben habe. Sie können dies bestätigen, indem Sie es ändern und feststellen, dass tatsächlich immer noch dieselbe Datei zurückgegeben wird.

Ilmari Karonen
quelle
Auch interessant, aber wie würde ich verfolgen, wann die Datei zuletzt geändert wurde und wann der Browser zum ersten Mal angezeigt wurde, um zu bestimmen, wann ich den Browser des Benutzers anweisen soll, sie erneut abzurufen (z. B. durch Ändern des Abfragewerts)?
ProgrammerGirl
1
Sie müssen nicht verfolgen, wann die Datei angezeigt wurde. Verfolgen Sie einfach, wann die Datei zuletzt geändert wurde (oder eine andere geeignete Eigenschaft davon), und fügen Sie sie in die Abfragezeichenfolge ein. Auf diese Weise ändert sich auch die URL, wenn sich die Datei ändert.
Ilmari Karonen
Sehr, sehr interessant. Also könnte ich vermutlich die "zuletzt geänderte" Eigenschaft der Dateien abrufen und einfach den Abfragewert korrekt machen?
ProgrammerGirl
1
Ja, das sollte funktionieren.
Ilmari Karonen
1
Es gibt keine wesentlichen Nachteile, die mir bekannt sind. Möglicherweise erhalten Sie doppelte Kopien Ihrer Bilder in Suchmaschinenindizes, aber zumindest die großen Suchmaschinen wie Google sind ziemlich schlau im Umgang mit solchen Dingen, da dies ein so häufiger Trick ist. In jedem Fall kann dieses Problem behoben werden, indem rel = "kanonische" HTTP-Header gesendet und Ihre Ablaufzeiten bescheiden gehalten werden (z. B. nur ein Monat oder eine Woche anstelle eines ganzen Jahres).
Ilmari Karonen
6

Es gibt mehr als einen Weg zum Cachen.

Bedingtes GET

Wenn Sie diese Bilder im Dateisystem speichern und direkt über den Webserver bereitstellen, verwenden Sie wahrscheinlich bereits das bedingte Abrufen . Der Web - Server verwendet Dateisystem - Metadaten automatisch einen ETAG - Header zu setzen, und wird automatisch antworten mit „304 Not Modified“ , wenn der Browser enthält If-Modified-Sinceoder If-MatchesHeader in seiner Anfrage. (Alle Browser werden.)

In diesem Fall wird nicht das gesamte Bild zurückgesendet, sodass Sie Bandbreiteneinsparungen erzielen. Es wird jedoch weiterhin eine GET-Anforderung ausgegeben, sodass Sie weiterhin den Overhead und die Latenz einer Anforderung haben.

Sie können die Anzahl der Anforderungen auf Kosten der Cache-Aktualität geringfügig verringern, indem Sie auf Ihrem Webserver Cache-ControlHeader mit einem public,max-age=NWert für Ihre Bilder festlegen . Dies bedeutet, dass Caches die Ressource höchstens max-ageSekunden lang behalten können, bevor sie überprüfen müssen, ob sie aktualisiert wurde.

HTTP definiert jedoch nur eine Möglichkeit, einen Cache-Eintrag ungültig zu machen, die möglicherweise nicht zur Semantik Ihrer Anwendung passt: Wenn Sie eine URL POSTEN oder PUTEN, die das Profilfoto aktualisiert, antworten Sie mit einem Location: [url of photo]Header, und der Cache-Eintrag für diese URL wird ungültig.

(Dies ist der Mechanismus, mit dem Sie eine Webseite mit Kommentaren zwischenspeichern und die Seite dann vom Browser zwangsweise neu laden lassen können, nachdem der Benutzer einen neuen Kommentar veröffentlicht hat. Der Browser antwortet auf ein POST /commentmit 303 See Otherund ein Location: /page/with/comment. Beachten Sie, dass dies nicht verwendet wurde wegen eines langjährigen Fehlers in Firefox zu arbeiten .)

Wenn Sie nicht viel Verkehr haben, ist dieser Ansatz zum Zwischenspeichern in Ordnung.

URLs ändern

Eine URL ist eine Darstellung einer Ressource. Eine andere Möglichkeit zum Verwalten des Caching besteht darin, die Cache-Parameter für die Ressource nicht zu ändern, sondern eine brandneue Ressource mit der Anweisung "Cache für immer" zu erstellen. Dies ist der Ansatz, den die "großen Jungs" bevorzugen, da sie keine zusätzlichen Anforderungen generieren können, wodurch sie viel Bandbreite sparen. Der Nachteil ist, dass viel mehr zusätzliche Buchhaltung erforderlich ist.

Hierfür gibt es zwei allgemeine Techniken.

Zeichenfolgen abfragen

Webserver ignorieren Abfragezeichenfolgen, wenn sie eine Datei aus dem Dateisystem bereitstellen. Caches jedoch nicht: /1.jpg?t=12345und /1.jpg?t=67890sind zwei völlig unterschiedliche, nicht miteinander verbundene Ressourcen, obwohl der Server glaubt, dass sie gleich sind.

Eine einfache Möglichkeit besteht darin, den Zeitstempel des Dateisystems als Abfragezeichenfolge anzuhängen, wenn Sie auf eine Ressource in Ihrem HTML-Code verweisen und einen langen ExpiresHeader festlegen . Der Browser speichert diese Ressource dann für immer im Cache und führt keine GETs durch, solange sich die Abfragezeichenfolge nicht ändert.

Ein Nachteil ist, dass es schwierig oder unmöglich ist, den Webserver über die neue URL für ein Element zu informieren, wenn Sie einen Cache zwangsweise ungültig machen möchten. Wenn ein Browser beispielsweise eine zwischengespeicherte HTML-Seite mit einer /1.jpg?v=1Referenz hat, aber zufällig den Eintrag für /1.jpg?v=1gelöscht hat (möglicherweise ist ihm die Datei oder der Speicherplatz ausgegangen), wird eine neue Anforderung an gesendet /1.jpg?v=1. Wenn sich das Bild in der Zwischenzeit geändert hat /1.jpg?v=2, lautet die richtige Antwort entweder:

  1. Servieren Sie die alte Version der Datei. Sie würden dies tun, wenn Sie möchten, dass alle Ressourcen zu einem bestimmten Zeitpunkt miteinander konsistent sind. Dies sollten Sie beispielsweise mit CSS-Dateien tun, da eine neue CSS-Datei mit einer alten HTML-Datei möglicherweise nicht richtig funktioniert!
  2. Leiten Sie mit auf die neue Version der Datei um 301 Moved Permanently. Sie würden dies tun, wenn Sie möchten, dass alle Ressourcen so neu wie möglich sind.

Beides ist mit einem Webserver allein nur schwer möglich. Daher müssen Sie eine Webanwendung auch für Bildanforderungen aufrufen, was sowohl komplizierter als auch ressourcenintensiver sein kann. Webserver können Dateien sehr schnell bereitstellen, sodass der Overhead einer Webanwendung möglicherweise Ihre Bandbreite und Latenzgewinne verschlingt.

Dateinamen

Anstatt eine Abfragezeichenfolge hinzuzufügen, ändern Sie den Dateinamen. Dies bedeutet, dass es einfach ist, mehrere Versionen von Dateien im Dateisystem zu speichern, aber Sie müssen wahrscheinlich Dateimetadaten speichern und andere Datenbankbücher führen, um Ihre Ressourcen und deren Namen im Auge zu behalten.


quelle
0

304 Not ModifiedWenn Sie den http-Status lesen , sollten Sie in der Lage sein, auf eine Download-Anfrage mit 304 zu antworten, und den Server anweisen, die zwischengespeicherten Daten zu verwenden, um sie erneut an den Browser zu senden. und lesen Sie diese Frage /programming/2978496/make-php-page-return-304-not-modified-if-it-hasnt-been-modified

Puggan Se
quelle
Interessant, aber ist dies eine "Pflaster" -Lösung für ein problematisches Dateischema, oder ist mein Dateischema gut und benötigt nur diese Caching-Funktion? Wie würde ich auch wissen, wann die Datei zuletzt geändert wurde und wann der Browser zum ersten Mal angezeigt wurde, um festzustellen, wann ich den Browser des Benutzers anweisen sollte, sie erneut abzurufen?
ProgrammerGirl
Ich bin nicht so vertraut damit, denke Francis Avila weiß viel mehr darüber
Puggan Se