【问题标题】:Proper way to change an image size on fly动态更改图像大小的正确方法
【发布时间】:2018-07-28 20:28:20
【问题描述】:

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

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

这里是代码sn-p:

$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 返回所有图像,即使它们根本没有更改?会不会增加服务器负载?

或者,也许,我应该将图像保存到另一个公共目录并将浏览器重定向到它?在一个页面上进行如此多的重定向需要多长时间(可能有很多图像)。搜索引擎优化呢?

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

【问题讨论】:

    标签: php image yii2


    【解决方案1】:

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

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

    嗯,这实际上是您应该关心的第一件事。通过 PHP 发送图像的效率将大大低于通过 webserver 发送图像的效率(但仍然非常快,尽管这可能取决于您的服务器配置)。让框架参与其中会慢得多(引导框架需要时间)。但是,如果您在每次请求时都调整图像大小,这一切都无关紧要——这将是这里的主要瓶颈。

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

    最重要的是:

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

    【讨论】:

    • 我认为你是对的!所以,我应该创建公共目录并将所有图像作为静态文件保存在那里。但我不知道如何避免重定向,因为用户可以随时请求任何图像参数。这就是为什么在收到特定请求之前我无法准备文件的原因。另一方面,浏览器无法处理请求,因为文件还不存在。那么,在没有reques->redirection->new_request链的情况下,如何知道我必须放入目录中的哪个文件?
    • 您可以尝试这种方法:stackoverflow.com/a/49712207/5812455 - 您可以创建 URL 规则来捕获对不存在图像的请求。这样,对现有图像的请求将由网络服务器处理,而对新图像的请求将被重定向到 PHP,因此您将能够生成缩略图并将其保存在请求的 URL 中。该 URL 的下一个请求将由 webserver 处理,因此 PHP 将仅参与第一个请求。
    猜你喜欢
    • 1970-01-01
    • 2023-03-05
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-29
    • 2020-08-09
    相关资源
    最近更新 更多