Как заставить веб-браузер НЕ кэшировать изображения - PullRequest
110 голосов
/ 24 сентября 2008

Фон

Я пишу и использую очень простой инструмент управления контентом на основе CGI (Perl) для двух бесплатных веб-сайтов. Он предоставляет администратору веб-сайта HTML-формы для событий, где они заполняют поля (дата, место, заголовок, описание, ссылки и т. Д.) И сохраняют их. В этой форме я разрешаю администратору загрузить изображение, связанное с событием. На странице HTML, отображающей форму, я также показываю предварительный просмотр загруженного изображения (тег HTML img).

Проблема

Проблема возникает, когда администратор хочет изменить изображение. Ему просто нужно нажать кнопку «Обзор», выбрать новое изображение и нажать «ОК». И это отлично работает.

Как только изображение загружено, мой внутренний CGI обрабатывает загрузку и корректно перезагружает форму.

Проблема в том, что показанное изображение не не обновляется. Старое изображение все еще отображается, хотя база данных содержит правильное изображение. Я сузил это до факта, что ИЗОБРАЖЕНИЕ КЕШИТСЯ в веб-браузере Если администратор нажимает кнопку «RELOAD» в Firefox / Explorer / Safari, все обновляется нормально, а новое изображение просто появляется.

Мое решение - не работает

Я пытаюсь управлять кешем, написав инструкцию HTTP Expires с датой очень далекой в ​​прошлом.

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

Помните, что я на административной стороне, и мне все равно, загружаются ли страницы немного дольше, потому что они всегда просрочены.

Но это тоже не работает.

Примечания

При загрузке изображения его имя не сохраняется в базе данных. Он переименован в Image.jpg (чтобы просто использовать его). При замене существующего изображения новым, имя также не меняется. Изменяется только содержимое файла изображения.

Веб-сервер предоставляется услугой хостинга / ISP. Использует Apache.

Вопрос

Есть ли способ заставить веб-браузер НЕ кэшировать вещи с этой страницы, даже изображения?

Я жонглирую опцией "сохранить имя файла" в базе данных. Таким образом, если изображение будет изменено, src тега IMG также изменится. Однако это требует много изменений по всему сайту, и я бы не стал этого делать, если у меня есть лучшее решение. Кроме того, это по-прежнему не будет работать, если новое загруженное изображение имеет то же имя (скажем, изображение немного фотофотошоплено и повторно загружено).

Ответы [ 15 ]

2 голосов
/ 16 марта 2014

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

У меня была очень похожая ситуация при загрузке изображений продукта в бэкэнд администратора для сайта, похожего на магазин, и в моем случае я решил, что лучшим вариантом будет использование javascript для принудительного обновления изображения без использования какого-либо изменения URL методы, которые другие люди уже упоминали здесь. Вместо этого я поместил URL-адрес изображения в скрытый IFRAME с именем location.reload(true) в окне IFRAME, а затем заменил свое изображение на странице. Это вынуждает обновлять изображение не только на странице, на которой я сейчас работаю, но и на любых последующих страницах, которые я посещаю - без необходимости запоминания клиентом или сервером каких-либо параметров строки запроса URL или идентификатора фрагмента.

Я написал код для этого в своем ответе здесь .

1 голос
/ 25 ноября 2015

С моей точки зрения отключить кэширование изображений - плохая идея. Совсем.

Основная проблема здесь - как заставить браузер обновлять изображение, если оно было обновлено на стороне сервера.

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

В моем случае это служба отдыха, которая возвращает изображение и присоединяет ETag в ответ. Сервис сохраняет хеш всех файлов, если файл изменен, хеш обновляется. Он отлично работает во всех современных браузерах. Да, для его реализации требуется время, но оно того стоит.

Единственное исключение - это favicons. По некоторым причинам это не работает. Я не мог заставить браузер обновить свой кеш со стороны сервера. ETags, Cache Control, Expires, заголовки Pragma, ничего не помогло.

В этом случае, добавление некоторого параметра random / version в URL, кажется, является единственным решением.

1 голос
/ 21 февраля 2010

Я предполагаю, что оригинальный вопрос касается изображений, хранящихся с некоторой текстовой информацией. Итак, если у вас есть доступ к текстовому контексту при генерации src = ... url, рассмотрите возможность хранения / использования CRC32 байтов изображения вместо бессмысленной случайной или временной метки. Затем, если отображается страница с большим количеством изображений, будут загружены только обновленные изображения. В конце концов, если сохранение CRC невозможно, его можно вычислить и добавить к URL во время выполнения.

1 голос
/ 24 сентября 2008

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

Если эта временная метка соответствует времени последнего обновления изображения, то вы можете кэшировать, когда вам нужно, и обслуживать новое изображение в нужное время.

0 голосов
/ 17 октября 2018

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

Для этого вы должны отслеживать ресурсы, которые могут потребоваться для синхронизации, и либо использовать xhr для проверки изображений с помощью динамической строки запроса, либо создавать изображение во время выполнения с помощью src, используя динамическую строку запроса. Затем используйте механизм вещания, чтобы уведомить всех Компоненты веб-страниц, которые используют ресурс для обновления, чтобы использовать ресурс с динамической строкой запроса, добавленной к его URL.

Наивный пример выглядит так:

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

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

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="mobile-web-app-capable" content="yes" />        
    <title>Resource Synchronization Test</title>
    <script>
function sync() {
    var xhr = new XMLHttpRequest;
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {            
            var images = document.getElementsByClassName("depends-on-resource");

            for (var i = 0; i < images.length; ++i) {
                var image = images[i];
                if (image.getAttribute('data-resource-name') == 'resource.bmp') {
                    image.src = 'resource.bmp?i=' + new Date().getTime();                
                }
            }
        }
    }
    xhr.open('GET', 'resource.bmp', true);
    xhr.send();
}
    </script>
  </head>
  <body>
    <img class="depends-on-resource" data-resource-name="resource.bmp" src="resource.bmp"></img>
    <button onclick="sync()">sync</button>
  </body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...