如何使用PHP获取浏览器缓存图像?

Joh*_*han 24 html php caching image

我对如何缓存图像完全不熟悉.

我使用PHP输出库中的所有图像,并希望浏览器缓存已显示的图像,因此PHP脚本不必再次输出相同的图像.我想要的只是图像显示得更快.

在调用图像时,我喜欢这样:

<img src="showImage.php?id=601">
Run Code Online (Sandbox Code Playgroud)

showImage.php-file做:

$id = (int) $_GET['id'];
$resultat = mysql_query("
    SELECT filename, id
    FROM Media 
    WHERE id = $id
");
$data = mysql_fetch_assoc($resultat);

...

//Only if the user are logged in
if(isset($_SESSION['user'])){
    header("Content-Type: image/jpeg");

    //$data['filename'] can be = dsSGKLMsgKkD3325J.jpg
    echo(file_get_contents("images/".$data['filename']."")); 
}
Run Code Online (Sandbox Code Playgroud)

Kor*_*nel 49

首先,如果您正在使用会话,则必须禁用session_cache_limiter(通过将其设置为nonepublic).它发送的标题对于缓存来说非常糟糕.

session_cache_limiter('none');
Run Code Online (Sandbox Code Playgroud)

然后发送Cache-Control: max-age=number_of_seconds和可选的等效Expires:标头.

header('Cache-control: max-age='.(60*60*24*365));
header('Expires: '.gmdate(DATE_RFC1123,time()+60*60*24*365));
Run Code Online (Sandbox Code Playgroud)

为了获得最佳的可缓存性,Last-Modified如果浏览器发送匹配的If-Modified-Since标题,则发送标题并回复状态304和空体.

header('Last-Modified: '.gmdate(DATE_RFC1123,filemtime($path_to_image)));
Run Code Online (Sandbox Code Playgroud)

为简洁起见,我在这里作弊(示例不验证日期),但只要您不介意浏览器永远保留缓存文件,它就是有效的:

if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
   header('HTTP/1.1 304 Not Modified');
   die();
}
Run Code Online (Sandbox Code Playgroud)


KiN*_*MaR 7

这是我用于304头支持的一些代码:

  /**
   * @return false if not cached or modified, true otherwise.
   * @param bool check_request set this to true if you want to check the client's request headers and "return" 304 if it makes sense. will only output the cache response headers otherwise.
   **/     
  protected function sendHTTPCacheHeaders($cache_file_name, $check_request = false)
  {
    $mtime = @filemtime($cache_file_name);

    if($mtime > 0)
    {
      $gmt_mtime = gmdate('D, d M Y H:i:s', $mtime) . ' GMT';
      $etag = sprintf('%08x-%08x', crc32($cache_file_name), $mtime);

      header('ETag: "' . $etag . '"');
      header('Last-Modified: ' . $gmt_mtime);
      header('Cache-Control: private');
      // we don't send an "Expires:" header to make clients/browsers use if-modified-since and/or if-none-match

      if($check_request)
      {
        if(isset($_SERVER['HTTP_IF_NONE_MATCH']) && !empty($_SERVER['HTTP_IF_NONE_MATCH']))
        {
          $tmp = explode(';', $_SERVER['HTTP_IF_NONE_MATCH']); // IE fix!
          if(!empty($tmp[0]) && strtotime($tmp[0]) == strtotime($gmt_mtime))
          {
            header('HTTP/1.1 304 Not Modified');
            return false;
          }
        }

        if(isset($_SERVER['HTTP_IF_NONE_MATCH']))
        {
          if(str_replace(array('\"', '"'), '', $_SERVER['HTTP_IF_NONE_MATCH']) == $etag)
          {
            header('HTTP/1.1 304 Not Modified');
            return false;
          }
        }
      }
    }

    return true;
  }
Run Code Online (Sandbox Code Playgroud)


mid*_*dus 5

您可以将生成的图像存储在名为“showImage”的目录中,以便您可以像这样嵌入它们

<img src="showimage/601.jpg" />
Run Code Online (Sandbox Code Playgroud)

然后,将.htaccess 文件放置在同一目录中,如果该文件不存在,该文件将调用 showImage.php?id=,例如:

<IfModule mod_rewrite.c>
   RewriteEngine On
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteRule ^(.*)\.jpg$ showImage.php?id=$1 [QSA,L]
</IfModule>
Run Code Online (Sandbox Code Playgroud)

只需在评论中阅读您想要进行客户端缓存:只需根据http://www.mnot.net/cache_docs/设置与缓存相关的 HTTP 标头


Ima*_*ist 5

如果您在输出消息之前使用php检查用户是否已登录,则您不希望浏览器缓存图像.

缓存的全部内容是调用服务器一次,然后再也不要再调用它.如果浏览器缓存图像,它将不会调用服务器,您的脚本将不会运行.相反,即使用户不再登录,浏览器也会从缓存中提取图像并显示它.这可能是一个非常大的安全漏洞.

  • 你仍然可以缓存*和*让浏览器调用服务器.它被称为缓存验证.你可以通过发送`Cache-control:private,must-revalidate`(私有,因为它不应该在用户之间共享)和'Last-Modified`或`ETag`头来实现.然后,当浏览器发送`If-Modified-Since`或`If-None-Match`时,如果自生成图像后没有任何变化,则响应状态为"304". (3认同)
  • 即使一个小时也不安全,唯一要做的就是希望黑客不要在特定时间尝试入侵。但是,从我在 http://www.mnot.net/cache_docs/#SCRIPT 上看到的情况来看,您似乎可以通过在 HTTP 标头中使用 `Cache-control: public, no-cache;` 来强制使用缓存进行身份验证(`no-cache` 实际上并不意味着没有缓存;名称有点偏离)。 (2认同)