【问题标题】:caching php served images缓存 php 提供的图像
【发布时间】:2017-12-26 09:59:59
【问题描述】:

我正在尝试像这样通过 php 提供图像:

img.php

<?php
session_start();
$file=$images_path.$_GET['id'].".jpg";
$lastModified = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT';
header("Cache-Control: private");
header("Content-type: image/jpeg");
header("ETag: ".md5_file($file));
header("Last-Modified: $lastModified");
header('Expires: ' . gmdate("D, d M Y H:i:s", ((60*60*24*1)+strtotime($lastModified))));//1 day expire

$db=new PDO("mysql:host=".$host.";dbname=".$db_name,$db_user,$db_psw);

$e=explode("/",$_GET['id']);
$post=$e[0];
$e=explode("_",$e[1]);
$user=$e[0];

$q="SELECT p.id FROM post p INNER JOIN files f ON p.id=f.post WHERE p.id=".$post." AND ";
if(!isset($_SESSION['id'])) $q.="p.privacy=1";
else
{
    $q.="(";
    $q.="p.user=".$_SESSION['id'];
    $q.=" OR p.privacy=1";
    $q.=" OR (p.privacy=2 AND p.user IN (".$_SESSION['id'];
    if(count($_SESSION['friends'])>0) $q.=",".implode(",",array_keys($_SESSION['friends']));
    $q.="))";
    $q.=" OR ".$_SESSION['id']." IN(SELECT tag FROM tags WHERE post=p.id)";
    $q.=")";
}
$q.=" AND f.user=".$user." AND (f.date IS NOT NULL"; if(isset($_SESSION['id'])) $q.=" OR f.user=".$_SESSION['id']; $q.=")";
$q.=" LIMIT 1";
$sql=$db->prepare($q); $sql->execute(); $post=$sql->fetch(PDO::FETCH_ASSOC);
if(!isset($post['id'])) {header("location:".$localhost); exit;}

if(file_exists($file))
{
    header('Content-Type:image/jpeg');
    readfile($file);
}
?>

index.php

<img src="img.php?id=1/1_1"><br>
<img src="img.php?id=1/1_2"><br>
<img src="img.php?id=1/1_3"><br>

但是速度很慢,而且不缓存图片,怎么办?

谢谢

更新 1

好的readfile(),我修好了

我更新了完整代码,这是必需的,因为我提供的图像不在公共根文件夹中,我必须检查当前登录的用户是否有权使用 mysql 查询中的会话查看图像

更新 2

我想要: 如果 files.date 为 NULL 则不缓存图像,或者缓存它并在它更改时强制重新加载 如果 files.date 不为空,则永远缓存图像 我不知道我应该使用哪些标题以及在哪里使用

更新 3

这是图片标题的屏幕截图

更新 4

如果资源被缓存,我想避免执行查询,那么使用会话变量来缓存图像的url呢?

【问题讨论】:

    标签: php mysql session caching


    【解决方案1】:

    这是一种非常奇怪的文件显示方式。您不需要fopen() 文件。只需 echo 每个文件的路径,然后让客户端直接下载文件。

    缓存应该会自动发生。

    【讨论】:

      【解决方案2】:

      尝试readfile(),因为它可以轻松读取和发送文件。

      session_start();
      /*connecting db*/
      /*query for checking images privacy through session user*/
      header('Content-Type:image/jpeg');
      readfile($_GET['id']);
      

      但如果大部分时间都花在读取数据库和检查安全性上,这可能不会有太大帮助。在这种情况下,也许您也应该向我们展示该代码,可能有一些方法可以加快速度。

      【讨论】:

      • 我更新了完整的代码,有什么需要改进的地方吗?
      【解决方案3】:

      您不需要 PHP 脚本即可返回带有 GET 参数的文件。您可以在 &lt;img&gt; 元素中生成路径并让它静态服务:

      <img src="<?php echo $id; ?>">
      

      如果由于某种原因您仍需要从 PHP 中返回图像,快速流式返回的最佳方法是使用readfile

      header('Content-Type:image/jpeg');
      readfile($_GET['id']);
      

      虽然您应该首先验证 GET 参数是一个良好的图像路径以确保安全。否则,您可能会将服务器上的其他文件返回给客户端。

      如果您不检查会话中的任何内容,则无需启动会话即可返回文件。


      现在我们看到更多代码并且您需要数据库调用,接下来我建议设置标题以指示浏览器在给定时间内缓存图像。适当的时间范围取决于所查询数据的更新频率。根据您的需要设置cache-control and possibly other headers

      除此之外,您还必须设法提高数据库/查询性能或完全避免使用服务器端缓存进行查询。

      【讨论】:

      • 是的,我必须检查当前登录的用户是否有权查看图像,请参阅更新的完整代码
      • 参见更新 2。你能给我一个如何使用这个标题的代码示例吗?
      • @Michele 有很多例子:stackoverflow.com/questions/12251989/…
      • 我尝试了您链接我的答案中的代码(请参阅更新),但每个图像加载仍然需要大约 1 秒。我做错了什么?
      • 没有错。 1s 是需要 db 查询的请求的好时机。在第一次请求后,浏览器应该将图像缓存 1 天。如果不是,我建议使用浏览器开发者工具来检查它所应用的标头和缓存规则。
      猜你喜欢
      • 1970-01-01
      • 2011-02-21
      • 1970-01-01
      • 2010-12-08
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多