Стоит ли менять всю структуру файлов моих пользовательских изображений, чтобы воспользоваться преимуществами простого кэширования в браузере?

9

На одном из моих мобильных сайтов я просто сохраняю изображения профиля моего пользователя как «1.jpg» в их пользовательской папке и постепенно отправляюсь оттуда за любыми дополнительными фотографиями, которые они загружают. Это означает, что всякий раз, когда они меняют свой профиль, например, имя файла остается неизменным.

Я хотел воспользоваться преимуществами кэширования изображений, чтобы одна и та же старая картинка не загружалась снова и снова при просмотре и повторном просмотре профиля пользователя, но в то же время я хочу, чтобы браузеры моих пользователей скачать новый, если он изменился.

Из того, что я читал, кажется, что единственный способ действительно сделать это - фактически использовать случайные имена файлов и отслеживать все эти имена файлов в БД, так что вы можете установить кэш с неограниченным сроком действия, в то время как в последнее время измененные фотографии снова вытащены, так как у них новое имя файла. Однако прелесть того, как я их структурировал до сих пор, заключается в том, что я могу полностью пропустить базу данных и получить доступ к файлам напрямую, поскольку их местоположение предсказуемо.

Итак, мой вопрос: стоит ли мне менять всю файловую структуру моего сайта, а также добавлять элемент БД, чтобы обеспечить вечное кэширование и автоматическую повторную загрузку при новой загрузке?

Это огромная задача, но если она будет сочтена достойной, у меня не будет проблем с продвижением вперед в этом кардинальном изменении. Я просто хочу убедиться, что именно так "большие мальчики" делают это, чтобы мне больше никогда не приходилось менять структуру файлов.

Спасибо.

ProgrammerGirl
источник

Ответы:

7

Одно из часто используемых решений - сделать так, чтобы URL-адреса вашего изображения выглядели примерно так:

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

Здесь /path/to/images/1.jpg- фактический URL-путь изображения, в то время как ?v=123456это просто фиктивный запрос, прикрепленный к концу URL-адреса. Строка запроса может быть любой - номер версии, временная метка, хэш содержимого изображения - при условии, что вы меняете его каждый раз, когда изображение изменяется, и сохраняете его тем же, когда оно не меняется.

Хитрость заключается в том, что веб-сервер, когда его просят предоставить такой URL, игнорирует строку запроса, поскольку URL фактически указывает на статический файл. Но для браузера пользователя (и любых промежуточных прокси-серверов) URL-адреса с разными строками запроса будут совершенно разными, и поэтому любое изменение строки запроса заставляет браузер перезагрузить файл.

Таким образом, вы можете настроить свой веб-сервер на отправку Expiresи Cache-ControlHTTP-заголовки, чтобы разрешить неопределенное кэширование, поскольку вы знаете, что вы можете принудительно выполнить перезагрузку, изменив строку запроса. Один из способов сделать это, если вы используете Apache с mod_expires , это поместить .htaccessфайл в каталог изображений со строками:

ExpiresActive On
ExpiresDefault "access plus 1 year"

Эта техника используется многими популярными сайтами. Например, если вы посмотрите на источник HTML этой самой страницы, вы обнаружите, что таблица стилей для него загружается с URL-адреса, например:

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

Здесь ?v=7cd8ea9d6f1eэто фиктивная строка запроса, как я описал выше; Вы можете подтвердить это, изменив его и убедившись, что он действительно возвращает тот же файл.

Илмари Каронен
источник
Также интересно, но как мне отследить, когда файл был последний раз изменен по сравнению с тем, когда браузер впервые просматривал страницу, чтобы определить, когда я должен сказать браузеру пользователя, чтобы он снова загрузил его (например, путем изменения значения запроса)?
ProgrammerGirl
1
Вам не нужно отслеживать, когда файл был просмотрен. Просто отследите, когда файл был изменен в последний раз (или какое-либо другое соответствующее ему свойство), и включите его в строку запроса. Таким образом, всякий раз, когда файл изменяется, URL-адрес также будет меняться.
Илмари Каронен
Очень, очень, интересно. Таким образом, я мог бы предположительно получить свойство «последний измененный» файлов и просто сделать это значение запроса правильным?
ProgrammerGirl
1
Да, это должно работать.
Илмари Каронен
1
Я не знаю каких-либо существенных недостатков. Вы можете получить дубликаты ваших изображений в индексах поисковых систем, но, по крайней мере, основные поисковые системы, такие как Google, довольно умно относятся к таким вещам, поскольку это такая распространенная уловка. В любом случае эту проблему можно устранить, отправив заголовки rel = "canonical" HTTP и сохранив скромное время истечения срока действия (скажем, всего один месяц или одну неделю вместо целого года).
Ильмари Каронен
6

Существует несколько способов кэширования.

Условный GET

Если вы храните эти изображения в файловой системе и обслуживаете их непосредственно через веб-сервер, вы, вероятно, уже используете условное получение . Веб-сервер будет автоматически использовать метаданные файловой системы для установки заголовка ETAG и автоматически ответит «304 Not Modified», если браузер включает If-Modified-Sinceили If-Matchesзаголовки в своем запросе. (Все браузеры будут.)

В этом случае все изображение не возвращается, поэтому вы экономите пропускную способность. Тем не менее, запрос GET будет по-прежнему выдаваться, поэтому вы по-прежнему будете иметь накладные расходы и задержку запроса.

Вы можете немного уменьшить количество запросов за счет свежести кэша, если ваш веб-сервер установит Cache-Controlзаголовки со public,max-age=Nзначением для ваших изображений. Это говорит о том, что кеши могут хранить ресурс не более max-ageсекунды, прежде чем проверять, обновляется ли он.

Однако HTTP определяет только один способ сделать недействительной запись в кэше, которая может не соответствовать семантике вашего приложения: если вы отправляете POST или PUT на URL, который обновляет фотографию профиля, ответьте Location: [url of photo]заголовком, и запись в кэше для этого URL будет признана недействительной.

(Это механизм, который позволяет вам кэшировать веб-страницу с комментариями, а затем принудительно перезагружать страницу браузером после того, как пользователь публикует новый комментарий. Браузер будет отвечать на запросы POST /commentс 303 See Otherи и Location: /page/with/comment. Обратите внимание, что это не использовалось работать в Firefox из-за давней ошибки .)

Если у вас нет большого трафика, такой подход к кешированию хорош.

Изменение URL

URL-адрес представляет собой представление ресурса, поэтому другой способ управления кэшированием состоит не в изменении параметров кэширования для ресурса, а в создании нового ресурса с директивой «вечный кеш». Это подход, который предпочитают «большие мальчики», потому что он позволяет им не генерировать лишних запросов, экономя им большую пропускную способность. Недостатком является то, что требуется гораздо больше дополнительной бухгалтерии.

Для этого есть два основных метода.

Строки запроса

Веб-серверы игнорируют строки запроса при обслуживании файла из файловой системы. Кэши, однако, не следует : /1.jpg?t=12345и /1.jpg?t=67890два совершенно разных, не связанных между собой ресурсы, даже если сервер думает , что они одинаковы.

Поэтому вы можете легко добавить временную метку файловой системы в виде строки запроса всякий раз, когда вы делаете ссылку на ресурс в html, и устанавливаете длинный Expiresзаголовок. Браузер будет кэшировать этот ресурс навсегда и не делать любые GETs, пока строка запроса не меняется.

Недостатком является то, что сложно или невозможно указать веб-серверу новый URL для элемента, если вы хотите принудительно аннулировать кэш. Например, если в браузере есть кэшированная HTML-страница со /1.jpg?v=1ссылкой, но в ней произошла очистка записи /1.jpg?v=1(возможно, ей не хватило места в файле или в памяти), он отправит новый запрос /1.jpg?v=1. Если за это время изображение изменилось на /1.jpg?v=2, правильным ответом будет либо:

  1. Служите старой версии файла. Вы бы сделали это, если бы вы хотели, чтобы все ресурсы были согласованы друг с другом, как они были в определенный момент времени. Это то, что вы должны делать с файлами CSS, например, поскольку новый файл CSS со старым файлом HTML может работать неправильно!
  2. Перенаправить на новую версию файла с помощью 301 Moved Permanently. Вы бы сделали это, если бы хотели, чтобы все ресурсы были как можно более новыми.

И то, и другое сложно сделать только с одним веб-сервером, а это означает, что вам нужно вызывать веб-приложение даже для запросов изображений, что может быть как более сложным, так и более ресурсоемким. Веб-серверы очень быстро обслуживают файлы, поэтому накладные расходы веб-приложения могут в конечном итоге поглотить вашу пропускную способность и увеличить задержки.

Имена файлов

Вместо добавления строки запроса вы меняете имя файла. Это означает, что в файловой системе легко хранить несколько версий файлов, но вам, вероятно, потребуется хранить метаданные файлов и вести другие записи в базе данных, чтобы отслеживать ваши ресурсы и их имена.


источник
0

прочитав о статусе http 304 Not Modified, вы должны быть в состоянии ответить на запрос на загрузку с 304 и тем самым сообщить серверу использовать кэшированные данные, вместо того, чтобы отправить их в браузер. и прочитайте этот вопрос /programming/2978496/make-php-page-return-304-not-modified-if-it-hasnt-been-modified

Puggan Se
источник
Интересно, но является ли это «вспомогательным средством» для решения проблемной файловой схемы, или моя файловая схема хороша и ей просто нужна эта способность кеширования? Кроме того, как я узнаю, когда файл был последний раз изменен по сравнению с тем, когда браузер впервые просматривал страницу, чтобы определить, когда я должен сказать браузеру пользователя, чтобы он снова загрузил его?
ProgrammerGirl
я не очень знаком с этим, думаю, что Фрэнсис Авила знает об этом больше
Puggan Se