即时更改图像大小的正确方法

时间:2018-07-28 20:28:21

标签: php image yii2

我有一个网站,上面有图片上传/显示功能。所有图像都保存在特定路径的文件系统中。

我在项目中使用Yii2框架。没有直接的方法来处理图像,所有图像都是由特定URL请求的。 ImageController处理URL并决定图像的大小调整。 ImageModel可以完成这项工作。用户获得图像内容。

这是代码段:

$file = ... // full path to image
...
$ext = pathinfo($file)['extension'];

if (file_exists($file)) {
    // return original
    return Imagine::getImagine()
        ->open($file)
        ->show($ext, []);
}

preg_match("/(.*)_(\d+)x(\d+)\.{$ext}/", $file, $matches);
if (is_array($matches) && count($matches)) {
    if (!file_exists("{$matches[1]}.{$ext}")) {
        throw new NotFoundHttpException("Image doen't exist!");
    }

    $options = array(
        'resolution-units' => ImageInterface::RESOLUTION_PIXELSPERINCH,
        'resolution-x' => $matches[2],
        'resolution-y' => $matches[3],
        'jpeg_quality' => 100,
    );

    return Imagine::resize("{$matches[1]}.{$ext}", $matches[2], $matches[3])
        ->show($ext, $options);
} else {
    throw new NotFoundHttpException('Wrong URL params!');
}

在本主题中,我们不讨论数据缓存。

因此,我想知道这种方法是否有效。可以通过PHP返回所有图像,即使它们完全没有变化也可以吗?会增加服务器负载吗?

或者,也许应该将图像保存到另一个公共目录,然后将浏览器重定向到该目录?单个页面上进行如此多次重定向需要多长时间(可能有很多图像)。 SEO呢?

我需要一个建议。解决此类任务的最佳实践是什么?

1 个答案:

答案 0 :(得分:2)

您应该考虑使用sendFile()xSendFile()发送文件-它比使用Imagine加载图像并通过show()显示图像要快得多。但是为此,您需要将最终映像保存在磁盘上,所以我们回到:

  

在本主题中,我们不讨论数据缓存。

嗯,这实际上是您应该关心的第一件事。与通过Web服务器发送图像相比,通过PHP发送图像的效率将大大降低(但仍然相当快,尽管这可能取决于您的服务器配置)。使框架参与其中会比较慢(引导框架需要时间)。但是,如果您将根据每个请求调整图像的大小,那么这一切都无关紧要-这将是这里的主要瓶颈。

只要您没有某些要求,这将使其成为不可能(例如,您需要在显示之前检查用户是否有权查看此图像),我建议将图像保存到公共目录并直接链接到它们(无任何重定向)。这将减轻您处理Web服务器已经对静态文件所做的工作(处理缓存头,304响应等)的麻烦,这将是最有效的解决方案。 如果无法做到这一点,请创建一个简单的PHP文件,该文件仅对用户send file,而不会引导整个框架。 如果您确实需要整个框架,请使用sendFile()xSendFile()发送文件。

最重要的是:

  1. 除了生成图像缩略图(应仅生成一次并缓存)之外,请勿将Imagine用于其他事情。
  2. 请勿链接到PHP页面,该页面将始终仅重定向到由Web服务器提供的真实图像。与通过PHP提供图像(您已经支付了通过PHP处理请求的价格)相比,它不会减少服务器负载,并且由于需要额外的请求来获取实际图像,因此您的网站对客户端的运行速度较慢(这可能会影响SEO)。
  3. 如果您需要通过PHP提供图片,请确保您设置了缓存标头,并且它与浏览器缓存配合得很好-您不想在每次网站刷新时都下载相同的图片。