Вимкнення кешу для деяких зображень


113

Я генерую кілька зображень за допомогою PHP lib.

Іноді браузер не завантажує новий створений файл.

Як я можу відключити кеш-пам'ять лише для динамічно створених мною зображень?

Примітка: я повинен використовувати те саме ім’я для створених зображень протягом часу.

Відповіді:


233

Поширене і просте рішення цієї проблеми, яке виглядає як хак, але є досить портативним, - додати до кожного запиту динамічного зображення довільно сформовану рядок запиту.

Так, наприклад -

<img src="image.png" />

Став би

<img src="image.png?dummy=8484744" />

Або

<img src="image.png?dummy=371662" />

З точки зору веб-сервера доступ до того самого файлу є доступним, але з точки зору браузера кешування не може здійснюватися.

Генерація випадкових чисел може статися або на сервері під час обслуговування сторінки (просто переконайтеся, що сама сторінка не кешована ...), або на клієнті (за допомогою JavaScript).

Вам потрібно буде перевірити, чи може ваш веб-сервер впоратися з цією хитрістю.


87
Замість випадкових чисел використовуйте часову позначку, яку змінили дані, або номер версії відображених даних.
lhunath


19
Зверніть увагу: Ви фактично не перешкоджаєте браузеру кешувати зображення, ви лише перешкоджаєте перегляду кешованого зображення. Застосування правильних заголовків до зображення - найкращий спосіб (див. Рішення лунату нижче). Оскільки таким чином ви також непотрібно заповнюєте кеш зображеннями, які не хочете кешувати, витрачаючи на те, щоб зменшити менше місця в кеші для речей, які ви насправді хочете кеш.
Джос

Я вважаю, що ця стаття пояснює причину такої поведінки.
Metalcoder

1
це насправді не працює, зображення потрібно промальовувати іншим способом (зазвичай при обрізанні зображення зображення залишається тим самим)
Бен

44

Стратегії кешування браузера можуть управлятися заголовками HTTP. Пам'ятайте, що вони справді лише натяк. Оскільки браузери дуже непослідовні в цьому (та будь-якому іншому) полі, вам знадобиться кілька заголовків, щоб отримати бажаний ефект на різних браузерах.

header ("Pragma-directive: no-cache");
header ("Cache-directive: no-cache");
header ("Cache-control: no-cache");
header ("Pragma: no-cache");
header ("Expires: 0");

1
це стосуватиметься всієї сторінки .... Я не можу відключити кеш лише для одного зображення (конкретного зображення з цієї сторінки)?
dole doug

5
@Thorpe: Це стосується відповідей HTTP. Те, що міститься у відповіді, не має значення. Будь то дані про зображення, HTML-дані чи інше. Якщо це не спрацювало, ви, ймовірно, не зробили це правильно. Перевірте заголовки HTTP на свою відповідь, щоб побачити, чи правильно вони були призначені.
lhunath

Я хотів би, щоб це спрацювало ... У Chrome немає жодних проблем, але Firefox 14 і IE 8 відмовляються оновлювати зображення, навіть надсилаючи вищезазначені заголовки. Це було б набагато більш чистим рішенням, ніж додавання довільних параметрів до рядка запиту. зітхання
Pawel Krakowiak

2
@PawelKrakowiak Зауважте, що додавання заголовків не працюватиме для вже кешованих зображень , оскільки браузер навіть не запитує про них сервера і тому ніколи не побачить заголовків. Вони працюватимуть із будь-якими запитами на зображення, зробленими після того, як ви додали їх.
lhunath

2
Це рішення призначене для програмістів, а не веб-дизайнерів. Я думав, що зазначу це, тому що не можна просто відкривати та зображувати та додавати заголовки до зображення, якщо вони самі не генерують зображення мовою програмування, і це, мабуть, бентежить коментаторів.
Брюс

13

Якщо вам потрібно зробити це динамічно у браузері за допомогою javascript, ось приклад ...

<img id=graph alt="" 
  src="http://www.kitco.com/images/live/gold.gif" 
  />

<script language="javascript" type="text/javascript">
    var d = new Date(); 
    document.getElementById("graph").src = 
      "http://www.kitco.com/images/live/gold.gif?ver=" + 
       d.getTime();
</script>

12

Рішення 1 не є великим. Це спрацьовує, але додавання хакейних рядків запитів випадкових або часових позначок до кінця файлів зображень змусить браузер повторно завантажувати та кешувати кожну версію кожного зображення, кожного разу при завантаженні сторінки, незалежно від погоди зображення змінилося чи ні на сервері.

Рішення 2 марно. Додавання nocacheзаголовків до файлу зображення не тільки дуже важко реалізувати, але це абсолютно непрактично, оскільки воно вимагає передбачити, коли воно буде потрібно заздалегідь , коли ви перший раз завантажуєте будь-яке зображення, яке, на вашу думку, може бути змінитися в якийсь момент у майбутньому .

Введіть позначки ...

Абсолютний кращий спосіб я знайшов , щоб вирішити цю проблему, щоб використовувати ETags всередині .htaccess файл в каталозі зображень. Далі вказується Apache надсилати унікальний хеш до браузера у заголовках файлів зображень. Цей хеш змінюється лише коли модифікується файл зображення, і ця зміна запускає браузер перезавантажувати зображення наступного разу, коли його запитують.

<FilesMatch "\.(jpg|jpeg)$">
FileETag MTime Size
</FilesMatch>

11

Я перевірив усі відповіді, і найкращим, здавалося, був (що ні):

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

по-перше.

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

Вирішення цієї проблеми було:

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

де ви в основному додаєте часову позначку unix, щоб параметр був динамічним і не кешував, він працював.

Однак моя проблема була дещо іншою: я завантажував зображення, створене на основі фліп-діаграми, і керував сторінкою за допомогою параметрів $ _GET. Я хотів, щоб зображення зчитувалося з кешу, коли параметр URL GET залишався однаковим, і не кешувати, коли параметри 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

Я знаю, що ця тема стара, але вона дуже добре займає Google. Я з’ясував, що введення цього у свій заголовок працює добре;

<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">

Сучасний браузер, на жаль, ігнорує ці директиви, тому це рішення може працювати лише на деяких браузерах, також воно вимкне кеш для всього, а не лише конкретних зображень
ZioCain

4

Я просто шукав рішення для цього, і відповіді вище не працювали в моєму випадку (і у мене недостатньо репутації, щоб коментувати їх). Виявляється, що принаймні для мого використання та браузера, який я використовував (Chrome на OSX), єдине, що, здавалося, запобігає кешування, це:

Cache-Control = 'no-store'

Для повноти я зараз використовую всі 3 "без кешу, немає магазину, необхідно переоцінити"

Тож у моєму випадку (подання динамічно генерованих зображень із Flask у Python) мені довелося зробити наступне, щоб сподіватися працювати в якомога більше браузерах ...

def make_uncached_response(inFile):
    response = make_response(inFile)
    response.headers['Pragma-Directive'] = 'no-cache'
    response.headers['Cache-Directive'] = 'no-cache'
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    response.headers['Expires'] = '0'
    return response

Просто виставлення відповіді в магазині було достатньо, щоб він працював на мене
бич192,

Це не лише в Chrome, а також для Firefox. Зараз це здається стандартом: developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control (див. Розділ " Запобігання кешування ").
Джино Мемпін

3

Зміна джерела зображення - це рішення. Дійсно це можна зробити, додавши до зображення часову позначку або випадкове число.

Краще було б додати контрольну суму, наприклад, даних, які зображує зображення. Це дозволяє кешувати, коли це можливо.


1

Додамо ще одне рішення до пучка.

Додавання унікальної струни в кінці - ідеальне рішення.

example.jpg?646413154

Наступне рішення розширює цей метод і надає можливість кешування і отримує нову версію, коли зображення оновлюється.

Коли зображення буде оновлено, час файлу буде змінено.

<?php
$filename = "path/to/images/example.jpg";
$filemtime = filemtime($filename);
?>

Тепер виведіть зображення:

<img src="images/example.jpg?<?php echo $filemtime; ?>" >

1
Це те, що я використовував через термін кешування.
ген

1

у мене була ця проблема і подолання, як це.

var newtags='<div class="addedimage"><h5>preview image</h5><img src="'+one+'?nocache='+Math.floor(Math.random() * 1000)+'"></div>';

0

Я використовував це для вирішення подібної проблеми ... показ лічильника зображень (від зовнішнього провайдера). Не оновлювався завжди правильно. І після додавання випадкового параметра все працює нормально :)

Я додав рядок дати, щоб забезпечити оновлення принаймні щохвилини.

зразок коду (PHP):

$output .= "<img src=\"http://xy.somecounter.com/?id=1234567890&".date(ymdHi)."\" alt=\"somecounter.com\" style=\"border:none;\">";

Це призводить до srcпосилання типу:

http://xy.somecounter.com/?id=1234567890&1207241014

0

Якщо у вас є URL-адреса зображення з жорстким кодом, наприклад: http://example.com/image.jpg, ви можете використовувати php, щоб додати заголовки до зображення.

Спочатку вам доведеться змусити апаш обробити jpg як php. Дивіться тут: Чи можливо виконати PHP з розширенням file.php.jpg?

Завантажте зображення (imagecreatefromjpeg) з файлу, а потім додайте заголовки попередніх відповідей. Використовуйте заголовок функції php, щоб додати заголовки.

Потім виведіть зображення за допомогою функції imagejpeg.

Зауважте, що дозволити php обробляти зображення у форматі jpg дуже небезпечно. Також майте на увазі, що я не перевіряв це рішення, тому від вас залежить, щоб він працював.


-1

Просто, надішліть одне місце заголовка.

Мій сайт, містить одне зображення, і після завантаження зображення воно не змінюється, я додаю цей код:

<?php header("Location: pagelocalimage.php"); ?>

Робота для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.