Кэширование запросов изображений через PHP - If-Modified-Since не отправляется - PullRequest
6 голосов
/ 24 июня 2009

Я передаю изображения через 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 M Y H: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);

}

Ответы [ 5 ]

6 голосов
/ 10 марта 2010

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 M Y H: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 M Y H:i:s', filemtime($fn)).' GMT', true, 200);
            header('Content-Length: '.filesize($fn));
            header('Content-Type: image/png');
            print file_get_contents($fn);
        }

    ?>
2 голосов
/ 24 июня 2009

Я считаю, что это должно быть

if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) >= $file_time)) {

Проверка, является ли измененное время большим или равным, а не равным. Хотя я понимаю, что два значения должны быть одинаковыми.

1 голос
/ 15 февраля 2013

Мне пришлось использовать решение Кейта с комбинацией сообщений Азкотоки и Жолти выше, чтобы все работало как нужно.

итак, последним примером будет:

<?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 M Y H: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 M Y H:i:s', filemtime($fn)).' GMT', true, 200);
        header('Content-Length: '.filesize($fn));
        header('Content-Type: image/png');
        print file_get_contents($fn);
    }

?>
1 голос
/ 05 июля 2010

Пройдя поиск, я нашел ответ. Браузер ничего не кэшировал (и не отправлял If-Modified-Since), пока я не отправил следующий заголовок:

Cache-Control: private;

После этого все работало нормально.

0 голосов
/ 11 октября 2010

Проверьте, используются ли сеансы на этой странице. Если это так, попробуйте следующее:

session_cache_limiter(false);

Если вышесказанное сработало, вот объяснение:

Механизм сессий Php отправляет некоторые автоматические заголовки, связанные с кэшем, чтобы улучшить конфиденциальность файлов cookie сеанса, избегая его кэширования промежуточными прокси:

http://php.net/manual/en/function.session-cache-limiter.php

Эти автоматические заголовки заставляют браузер никогда не отправлять заголовок If-Modified-Since, поскольку они инструктируют его вообще не выполнять никакого кэширования.

...