通过PHP缓存图像请求 - 如果 - 已修改 - 自未发送

时间:2009-06-24 14:11:53

标签: php apache caching header

我正在通过php提供图像并且在设置它时会出现一些问题,以便使用304标头进行响应以节省加载时间。

我在php.net上找到的大部分代码。它可以工作,但总是以200响应。由于某种原因,即使我最初发送Last-Modified标头,也没有收到任何请求的If-Modified-Since标头。这是在一个apache服务器。知道什么可能是错的吗?

Example here.

此页面将从磁盘加载图像并将其显示到浏览器,同时发送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 个答案:

答案 0 :(得分:6)

Mandor dot net上的mandor posted a solution在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);
        }

    ?>

答案 1 :(得分:2)

我认为应该是

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

检查修改时间是否大于或等于而不是等于。虽然我明白这两个值应该是相同的。

答案 2 :(得分:1)

经过一段时间的搜索,我找到了答案。在我发送以下标题之前,浏览器没有缓存任何内容(并且没有发送If-Modified-Since):

Cache-Control: private;

这样做之后一切正常。

答案 3 :(得分:1)

我不得不使用Keith的解决方案,结合上面的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 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);
    }

?>

答案 4 :(得分:0)

检查该页面上是否正在使用会话,如果是,请尝试:

session_cache_limiter(false);

如果上述方法有效,请在下面解释:

Php的会话机制发送一些与缓存相关的自动头文件,以改善会话cookie隐私,避免被中间代理缓存:

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

这些自动标头导致浏览器不发送If-Modified-Since标头,因为它们指示它根本不执行任何缓存。