Как заставить веб-браузер НЕ кэшировать изображения - 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 ]

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

Армин Ронахер имеет правильную идею. Проблема в том, что случайные строки могут сталкиваться. Я бы использовал:

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

Где "1222259157.415" - текущее время на сервере.
Время генерируется Javascript с performance.now() или Python с time.time()

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

Простое исправление: прикрепить произвольную строку запроса к изображению:

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

Что говорит HTTP RFC:

Cache-Control: no-cache

Но это не очень хорошо работает:)

18 голосов
/ 17 сентября 2012

Я использую Функция изменения времени файла PHP , например:

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

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

14 голосов
/ 10 сентября 2013

Я бы использовал:

<img src="picture.jpg?20130910043254">

где "20130910043254" - время изменения файла.

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

Я думаю, что есть два типа простых решений: 1) те, которые приходят на ум первыми (простые решения, потому что их легко придумать), 2) те, с которыми вы сталкиваетесь после обдумывания вещей (потому что они просты в использовании). Очевидно, вы не всегда выиграете, если решите все обдумать. Но второй вариант, скорее всего, недооценен. Подумайте, почему php так популярен;)

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

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

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 изображения должно быть достаточно, но, поскольку мы хотим быть пуленепробиваемыми.

6 голосов
/ 31 марта 2016

Я НОВЫЙ кодер, но вот что я придумала, чтобы браузер не кэшировал и не держал на своих веб-камерах:

<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: работает при обновлении веб-страницы и при повторном посещении веб-сайта (без обновления). ХРОМ: работает только при обновлении веб-страницы (даже после повторного посещения). SAFARI и iPad: не работает, я должен очистить историю и веб-данные.

Есть идеи по поводу SAFARI / iPad?

5 голосов
/ 30 декабря 2017

использование Класс = "NO-CACHE"

образец HTML:

<div>
    <img class="NO-CACHE" src="images/img1.jpg" />
    <img class="NO-CACHE" src="images/imgLogo.jpg" />
</div>

JQuery:

    $(document).ready(function ()
    {           
        $('.NO-CACHE').attr('src',function () { return $(this).attr('src') + "?a=" + Math.random() });
    });

JavaScript:

var nods = document.getElementsByClassName('NO-CACHE');
for (var i = 0; i < nods.length; i++)
{
    nods[i].attributes['src'].value += "?a=" + Math.random();
}

Результат: src = "images / img1.jpg" => src = "images / img1.jpg? a = 0.08749723793963926"

4 голосов
/ 19 ноября 2015

Я проверил все ответы в Интернете, и лучший из них, похоже, был: (на самом деле это не так)

<img src="image.png?cache=none">

сначала.

Однако, если вы добавите параметр cache = none (который является статическим словом "none"), это ничего не изменит, браузер все еще загружается из кэша.

Решение этой проблемы было:

<img src="image.png?nocache=<?php echo time(); ?>">

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

Однако моя проблема была немного другой: Я загружал на лету сгенерированное изображение php диаграммы и управлял страницей параметрами $ _GET. Я хотел, чтобы изображение считывалось из кэша, когда параметр GET URL-адреса остается неизменным, и не кэшировалось при изменении параметров GET.

Чтобы решить эту проблему, мне нужно было хэшировать $ _GET, но поскольку это массив, вот решение:

$chart_hash = md5(implode('-', $_GET));
echo "<img src='/images/mychart.png?hash=$chart_hash'>";

Редактировать

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

echo "<img src='/images/mychart.png?hash=" . filemtime('mychart.png') . "'>";

filemtime () возвращает время изменения файла.

4 голосов
/ 25 сентября 2008

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

Измените это, и вы исправили свою проблему. Я использую метки времени, как и в решениях, предложенных выше: Image- .jpg

Предположительно, любые проблемы, которых вы избегаете, сохраняя одно и то же имя файла для изображения, можно преодолеть, но вы не говорите, какие они есть.

2 голосов
/ 10 января 2018

Добавить отметку времени <img src="picture.jpg?t=<?php echo time();?>">

всегда даст вашему файлу случайное число в конце и остановит его кеширование

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...