Вопрос по php, caching, apache, header – Кэширование запросов изображений через PHP - If-Modified-Since не отправляется

6

Я передаю изображения через php, и у меня возникают некоторые проблемы с настройкой так, чтобы он отвечал 304 заголовками, чтобы сэкономить время загрузки.

Большую часть кода ниже я нашел на php.net. Это работает, однако ВСЕГДА отвечает 200.For some reason the If-Modified-Since header is not being received on any requests even though I am sending the Last-Modified header initially. Это делается на сервере Apache. Есть идеи, что может быть не так?

Пример тут.

Эта страница загрузит изображение с диска и отобразит его в браузере, а также отправит заголовок Last-Modified. Если вы обновите страницу, браузер не отправит заголовок If-Modified-Since, как должен.

<code>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);

}
</code>
+1 за вопрос! Очень похожая проблема с заголовком If-Modified Since, возвращающим полный контент вместо 304:stackoverflow.com/questions/4810806/… Sam

Ваш Ответ

5   ответов
6

mandor at mandor dot net опубликовал решение в документации по PHP.net для функции заголовка, которая работала для меня:

<?php

        // Test image..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);
        }

    ?>
1

ки и Жолти выше, чтобы все работало как нужно.

итоговый пример:

<?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);
    }

?>
Это сработало для меня, в сочетании с использованием $ _SERVER [& quot; HTTP_IF_MODIFIED_SINCE & quot;] вместо $ headers
0

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

session_cache_limiter(false);

Если вышеупомянутое сработало, вот объяснение:

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

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

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

1

не отправлялIf-Modified-Since) пока я не отправил следующий заголовок:

Cache-Control: private;

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

2

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

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

Да, я очень странно проверил и _SERVER, и apache_request_headers (). Может быть, я должен привести пример, чтобы показать. Louis W
Любая идея, почему 'If-Modified-Since & apos; не получен php для последующих запросов? Я отлаживаю значение $ headers, и оно там никогда не появляется. Предположительно, все, что вам нужно сделать, это установить 'Last-Modified & apos; и это должно появиться. Louis W
Вы уверены, что ваш браузер отправляет его? Используйте такой плагин, как LiveHTTPHeaders, чтобы убедиться в этом. Также, когда я делаю это, я использую $ _SERVER [], а не apache_request_headers ()

Похожие вопросы