Я обслуживаю изображения через php и имею некоторые проблемы с настройкой, чтобы ответить 304 заголовками, чтобы сэкономить время загрузки.
Большая часть кода ниже я нашел на php.net. Он работает, однако ВСЕГДА отвечает 200. По какой-то причине заголовок If-Modified-Since не принимается ни по каким запросам, даже если я отправляю заголовок Last-Modified изначально. Это выполняется на сервере Apache. Любая идея, что может быть неправильным?
Пример здесь.
Эта страница загрузит изображение с диска и отобразит его в браузере вместе с отправкой заголовка Last-Modified. Если вы обновите страницу, браузер не отправит заголовок If-Modified-Since, как следует.
define('SITEPATH', (dirname($_SERVER['SCRIPT_NAME']) == '/') ? '/' : dirname($_SERVER['SCRIPT_NAME']).'/'); $load_path = $_SERVER['DOCUMENT_ROOT'] . SITEPATH . 'fpo_image.jpg'; // Get headers sent by the client. $headers = apache_request_headers(); $file_time = filemtime($load_path); header('Cache-Control: must-revalidate'); header('Last-Modified: '.gmdate('D, d MYH:i:s', $file_time).' GMT'); if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $file_time)) { header('HTTP/1.1 304 Not Modified'); header('Connection: close'); } else { header('HTTP/1.1 200 OK'); header('Content-Length: '. filesize($load_path)); header('Content-type: image/jpeg'); readfile($load_path); }
Я считаю, что это должно быть
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) >= $file_time)) {
Проверка того, что измененное время больше или равно, чем просто равно. Хотя я понимаю, что два значения должны быть одинаковыми.
mandor at mandor dot net опубликовал решение в документации PHP.net для функции заголовка, которая работала для меня:
<?php // Test image. $fn = '/test/foo.png'; // Getting headers sent by the client. $headers = apache_request_headers(); // Checking if the client is validating his cache and if it is current. if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) { // Client's cache IS current, so we just respond '304 Not Modified'. header('Last-Modified: '.gmdate('D, d MYH:i:s', filemtime($fn)).' GMT', true, 304); } else { // Image not cached or cache outdated, we respond '200 OK' and output the image. header('Last-Modified: '.gmdate('D, d MYH:i:s', filemtime($fn)).' GMT', true, 200); header('Content-Length: '.filesize($fn)); header('Content-Type: image/png'); print file_get_contents($fn); } ?>
После поиска какое-то время я нашел ответ. Браузер ничего не кэшировал (и не отправил If-Modified-Since
), пока я не отправил следующий заголовок:
Cache-Control: private;
После этого все работало нормально.
Мне пришлось использовать решение Кейта с комбинацией сообщений azkotoki и Zsolti выше, чтобы все работало по мере необходимости.
поэтому в качестве примера можно привести:
<?php // Test image. $fn = '/test/foo.png'; session_cache_limiter(false); header('Cache-Control: private'); // Getting headers sent by the client. $headers = apache_request_headers(); // Checking if the client is validating his cache and if it is current. if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == filemtime($fn))) { // Client's cache IS current, so we just respond '304 Not Modified'. header('Last-Modified: '.gmdate('D, d MYH:i:s', filemtime($fn)).' GMT', true, 304); } else { // Image not cached or cache outdated, we respond '200 OK' and output the image. header('Last-Modified: '.gmdate('D, d MYH:i:s', filemtime($fn)).' GMT', true, 200); header('Content-Length: '.filesize($fn)); header('Content-Type: image/png'); print file_get_contents($fn); } ?>
Проверьте, используются ли сеансы на этой странице. Если да, попробуйте следующее:
session_cache_limiter(false);
Если это было сделано, вот объяснение:
Механизм сеанса Php отправляет некоторые автоматические заголовки, связанные с кешем, для улучшения конфиденциальности cookie сеанса cookie, избегая его кэширования промежуточными прокси-серверами:
http://php.net/manual/en/function.session-cache-limiter.php
Эти автоматические заголовки заставляют браузер никогда не отправлять заголовок If-Modified-Since, поскольку они инструктируют его не выполнять никакого кэширования вообще.