Как кэшировать динамически создаваемые изображения?

У меня есть скрипт php, который генерирует *.png картинки, но не хранит их на сервере. Эти изображения будут показаны одному и тому же пользователю несколько раз. Я ищу способ кэшировать эти картинки. Я могу отправить заголовок статуса 304, браузер также объявляет веб-страницу как кэшированную при первом обновлении (как это видно в веб-инспекторе), но веб-страница отображается пустой. После второго обновления даже веб-инспектор показывает пустым.

Может ли кто-нибудь помочь мне и сказать, где я запутался?

Заметки:

  • Я прочитал этот пост, но он мне не помог.
  • Использование MAMP (версия PHP 7.0.10)
  • Я новичок, извиняюсь за ужасный код.

Вот основные строки файла:

session_start();
header("Content-type: image/jpeg");
//A little require_once() here on some functions stored in an other file.
$originalSource = getSource($_GET['src']);
if (isset($_COOKIE[sha1($originalSource)]) && $_COOKIE[sha1($originalSource)]) {
    header("HTTP/1.1 304 Not Modified");
    die;
} else {
    setcookie (sha1($originalSource), true, time()+10);
    $offset = 10;
    $expire = "Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT";
    header($expire);
    header("Cache-Control: max-age=".$offset);
    header("Last-Modified: Wed, 25 Feb 2015 12:00:00 GMT");
}
//The entire image generation process after this

Спасибо за вашу помощь

1 ответ

Решение

Здесь ваш сервер решает, думает ли он, что браузер должен сохранять изображение в кэше или нет. Очевидно, это вряд ли авторитет в этом. Существует несколько причин, по которым браузер не может кэшировать изображение, например, если вы открываете инструменты инспектора (которые обычно отключают кэширование).

В браузере есть механизм информирования сервера о состоянии его кэша: заголовки HTTP If-None-Match для ETags и If-Modified-Since для истечения срока действия. Если в запросе присутствует любой из этих двух заголовков, это означает, что браузер все еще имеет копию кэшированного ресурса и с радостью примет 304 ответ вместо загрузки ресурса снова.

Если вы установите ETag заголовок в вашем ответе, браузер сделает еще один запрос, используя If-None-Match (это существенно заменяет ваш механизм cookie, более надежно); если вы просто установите срок действия, браузер снова проверит сервер, используя If-Modified-Since заголовок. Это то, что вы должны основать свой 304 ответить на.

Пример использования ETags:

$hash = sha1($originalSource);

header("Expires: " . gmdate("D, d M Y H:i:s", time() + $offset) . " GMT");

if (
    isset($_SERVER['HTTP_IF_NONE_MATCH']) &&
    trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $hash
) {
    header("HTTP/1.1 304 Not Modified");
    exit;
}

header("Content-type: image/jpeg");
header("Cache-Control: max-age=$offset");
header("ETag: \"$hash\"");

// output image
Другие вопросы по тегам