【问题标题】:Image generated with PHP caching使用 PHP 缓存生成的图像
【发布时间】:2012-12-10 15:52:20
【问题描述】:

我有一个脚本,它在服务器上使用 PHP 生成图像,格式为 image.png。然后我使用<img src="http://domain.com/images/image.png" /> 在不同的地方使用这张图片。

我遇到的问题是,即使图像每 30 分钟重新生成一次,但它似乎已被缓存,并且在我转到 http://domain.com/images/image.png 然后 ctrl+shift+refresh 之前不会显示新值。

有什么办法可以保持图片名称不变,但始终显示最新版本的图片?

【问题讨论】:

    标签: php html apache image-caching


    【解决方案1】:

    这发生在浏览器缓存超过 30 分钟。由于您的图像每 30 分钟生成一次,您应该相应地设置 ExpiresCache-control 标头

    查看这些标题。

    Expires: Mon, 10 Dec 2012 16:25:18 GMT
    Cache-Control: max-age=1800
    

    此处Expries 设置为从现在起 30 分钟后的时间 (Date: Mon, 10 Dec 2012 15:55:18 GMT)。并且Cache-Control也需要设置。单位在这里是第二的。

    我将这些标头用于缓存持续时间为 60 分钟的图像生成站点。这些是我缓存它所遵循的规则。

    1. 检查图像文件是否存在
      • 如果它比我的缓存持续时间旧,请删除它,然后生成新图像。
    2. 如果图像文件不存在
      • 生成图片并保存
    3. 现在我们有了一个有效的图像。
    4. 计算图片的文件修改日期并加上缓存时长。
    5. 使用适当的标题提供它,其中过期日期将是我们在步骤 4 中计算的值。

    【讨论】:

    • 我可以通过设置标题在我的脚本中执行此操作,即使我正在生成图像,然后将其保存为 image.png?
    • 这些标题会影响脚本的输出。如果您输出的是图像,那么这些标头将处理浏览器缓存。如果脚本只是生成图像而不是输出到浏览器,它会影响html。
    【解决方案2】:

    有几个选项,具体取决于您的情况。如果“images/image.png”是服务器上的实际文件并且您正在直接访问它,那么您必须更改文件夹上的缓存设置或使用 .htaccess 通知浏览器重新发送它。

    <FilesMatch "\.(ico¦pdf¦flv¦jpg¦jpeg¦png¦gif¦js¦css¦swf)$">
    ExpiresDefault A604800
    Header set cache-control: "no-cache, public, must-revalidate"
    </FilesMatch> 
    

    如果您使用 PHP 查找图像并返回它,您可以使用 PHP 发送标头。

    header("Expires: ".gmdate("D, d M Y H:i:s", time()+1800)." GMT");
    header("Cache-Control: max-age=1800");
    

    为了完美地使用 PHP,你可以检查它是否真的被修改了

    $last_modified_time = @filemtime($file);
    header("Expires: ".gmdate("D, d M Y H:i:s", $last_modified_time+1800)." GMT"); 
    //change with $last_modified_time instead of time().
    //Else if you request it 29mins after it was first created, you still have to wait 30mins
    //but the image is recreated after 1 min.
    
    header("Cache-Control: max-age=1800");
    header("Vary: Accept-Encoding");
    
    // exit if not modified
    if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
        if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) { 
            header("HTTP/1.1 304 Not Modified"); 
            return;
        }
    }
    

    【讨论】:

    • 如果您发送Expires 标头浏览器将不会请求它。但在其过期浏览器可能会请求 IF modified since 标头。这样你就省去了很多不必要的http请求。
    【解决方案3】:

    您可以尝试使用 PHP 加载图像:

    <?php
    //generateImage.php
    
    $path = "xxxx/xxx.jpg";
    $img =imagecreatefromjpeg($path);
    
    header("Content-Type: image/jpeg");
    imagejpeg($img);
    imagedestroy($img);
    
    ?>
    

    然后像这样调用图像:

    <img src="http://domain.com/generateImage.php" />
    

    【讨论】:

      猜你喜欢
      • 2013-03-19
      • 2015-07-11
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 1970-01-01
      相关资源
      最近更新 更多