ambroisemaupate/intervention-request

一个可定制的干预图像包装器,用于在URL上使用图像简单重采样功能并配置缓存。

v4.1.1 2024-09-08 11:26 UTC

README

一个可定制的 干预图像 包装器,用于在URL上使用图像简单重采样功能并配置缓存。

Build Status Packagist Packagist

现成的 Docker 镜像

Intervention Request 现在可以作为独立的Docker服务器使用,可用于您需要的任何CMS或语言。它声明了两个卷:一个用于您的图像存储,另一个用于缓存文件。

  • /var/www/html/web/images: 您可以将其设置为只读,以防止任何写操作
  • /var/www/html/web/assets: 您必须将其设置为可写,以允许写入缓存文件
docker pull ambroisemaupate/intervention-request;
# Make sure to share your volume with READ-ONLY flag
docker run -v "/my/images/folder:/var/www/html/web/images:ro" -p 8080:80/tcp ambroisemaupate/intervention-request;

垃圾收集器每小时作为 crontab 作业运行,并将删除超过 $IR_GC_TTL 秒创建的缓存文件。您仍然可以使用 docker compose exec -u www-data intervention bin/intervention gc:launch 命令手动执行它。

使用本地文件系统或远程文件系统

InterventionRequest 是基于 Flysystem 库构建的,用于抽象对您本地图像的访问。然后您可以将所有图像存储在 AWS 存储桶或 Scaleway 对象存储中,并在运行时处理它们。处理后的图像仍然存储在 InterventionRequest 本地存储中。这个新的文件系统抽象层允许并行运行多个 InterventionRequest Docker 容器,但仍然使用相同的图像后端存储,或者简单地将媒体存储逻辑从 InterventionRequest 应用程序中分离出来。

InterventionRequest 对象需要一个 FileResolverInterface,可以是 LocalFileResolverFlysystemFileResolver,然后 FlysystemFileResolver 必须提供一个配置了任何 Flysystem 适配器的 League\Flysystem\Filesystem 对象。

如果您希望使用 ambroisemaupate/intervention-request Docker 镜像,只有 AWS 适配器才有环境变量可用。

Docker Compose 示例

version: '3'
services:
    intervention:
        image: ambroisemaupate/intervention-request:latest
        volumes:
            # You can store cache in a volume too
            #- cache:/var/www/html/web/assets
            - ./my/images/folder:/var/www/html/web/images:ro
        # You can override some defaults below
        environment:
            IR_GC_PROBABILITY: 400
            IR_GC_TTL: 604800
            IR_RESPONSE_TTL: 31557600
            IR_USE_FILECHECKSUM: 0
            IR_USE_PASSTHROUGH_CACHE: 1
            IR_DRIVER: gd
            IR_CACHE_PATH: /var/www/html/web/assets
            IR_IGNORE_PATH: /assets
            IR_DEFAULT_QUALITY: 80
            ## If using local storage file system
            IR_IMAGES_PATH: /var/www/html/web/images
            ## If using an AWS or Scaleway Object storage file system 
            IR_AWS_ACCESS_KEY_ID: 'changeme'
            IR_AWS_ACCESS_KEY_SECRET: 'changeme'
            IR_AWS_ENDPOINT: 'https://s3.fr-par.scw.cloud'
            IR_AWS_REGION: 'fr-par'
            IR_AWS_BUCKET: 'my-bucket'
            IR_AWS_PATH_PREFIX: 'images'
        ports:
            - 8080:80/tcp
        # Uncomment lines below for Traefik usage
        #labels:
        #    - "traefik.enable=true"
        #    - "traefik.http.services.intervention.loadbalancer.server.scheme=http"
        #    - "traefik.http.services.intervention.loadbalancer.server.port=80"
        #    - "traefik.http.services.intervention.loadbalancer.passhostheader=true"
        #    # Listen HTTP
        #    - "traefik.http.routers.intervention.entrypoints=http"
        #    - "traefik.http.routers.intervention.rule=Host(`intervention.test`)"
        #    - "traefik.http.routers.intervention.service=intervention"
        #networks:
        #    - default
        #    - frontproxynet

如果您不打算将此库嵌入到PHP应用程序中,则无需继续阅读。

安装

composer require ambroisemaupate/intervention-request

Intervention Request 基于 symfony/http-foundation 组件来处理HTTP请求、响应和基本文件操作。它使用简单的文件缓存管理包装了 Intervention/image 功能。

配置

使用专用类来配置图像请求参数。在创建 InterventionRequest 对象之前,必须实例化一个新的 AM\InterventionRequest\Configuration 对象,并设置缓存和图像路径。

$conf->setCachePath(APP_ROOT.'/cache');
$conf->setImagesPath(APP_ROOT.'/images');

此代码将在与您的 PHP 脚本相同的文件夹中创建一个包含 cacheimages 文件的配置。 请注意,在默认的 index.php 文件中,images 路径定义为 /test 文件夹,以便使用测试图像。您应该始终将此路径设置为您的网站图像文件夹,以防止处理其他文件。

您可以使用它们相应的 setter 编辑每个配置参数。

  • setCaching(true|false):是否使用请求缓存将生成的图像存储在文件系统中(默认:true);
  • setCachePath(string):图像缓存文件夹路径;
  • setUsePassThroughCache(true|false):是否使用 pass-through 缓存来绕过 PHP 处理一次图像生成;
  • setDefaultQuality(int):默认 90,当用户未指定时设置质量量;
  • setImagesPath(string):请求图像的根路径;
  • setTtl(integer):缓存图像的存活时间,供内部垃圾收集器使用(默认:1 周);
  • setResponseTtl(integer):图像 HTTP 响应的存活时间,供浏览器和代理缓存使用(默认:1 年);
  • setDriver('gd'|'imagick'):选择可用的 Image Intervention 驱动器;
  • setTimezone(string):PHP 时区用于构建用于缓存的 \DateTime 对象。如果您在 php.ini 文件中没有设置它,请在这里设置;
  • setGcProbability(integer):垃圾收集器概率除数。垃圾收集器启动概率是 1/$gcProbability,其中概率为 1/1 将在每次请求时启动 GC;
  • setUseFileChecksum(true|false):使用文件校验和来测试文件是否不同,即使其名称未更改。此选项可能对大文件很贪婪。(默认:false)。
  • setJpegoptimPath(string)可选 — 告知 jpegoptim 二进制文件的 JPEG 后处理位置(除非您需要坚持 100 的质量,否则不适用)。
  • setPngquantPath(string)可选 — 告知 pngquant 二进制文件的 PNG 后处理位置。 强烈建议使用此后处理工具,因为 PNG 没有它将不会得到优化。
  • setLossyPng(true|false)可选 — 告知 pngquant/pingo 二进制文件使用 调色板 有损压缩(默认:false);

可用的操作

适合位置

由于 URL 重新编写,align 过滤器只能接受一个或两个字母作为值。如果没有指定对齐过滤器,则使用 center

使用独立入口点

index.php 文件允许您将其用作独立应用程序。您可以根据需要调整配置来设置您本地的图像文件夹或启用/禁用缓存。

在您的 Web 服务器根目录中设置它,在 intervention-request 文件夹中,并调用此 URL(例如,在计算机上使用包含测试图像的 MAMP/LAMP):https://:8888/intervention-request/?image=images/testPNG.png&fit=100x100

将作为库在项目中使用

InterventionRequest 类与 SymfonyRequestResponse 无缝协作。将其集成到 Symfony 控制器方案中非常容易。

use AM\InterventionRequest\Configuration;
use AM\InterventionRequest\InterventionRequest;
use AM\InterventionRequest\LocalFileResolver;

/*
 * A test configuration
 */
$conf = new Configuration();
$conf->setCachePath(APP_ROOT.'/cache');
$conf->setImagesPath(APP_ROOT.'/files');
// Comment this line if jpegoptim is not available on your server
$conf->setJpegoptimPath('/usr/local/bin/jpegoptim');
// Comment this line if pngquant is not available on your server
$conf->setPngquantPath('/usr/local/bin/pngquant');

$fileResolver = new LocalFileResolver($conf->getImagesPath());

/*
 * InterventionRequest constructor asks 2 objects:
 *
 * - AM\InterventionRequest\Configuration
 * - AM\InterventionRequest\FileResolverInterface
 */
$intRequest = new InterventionRequest($conf, $fileResolver);
// Handle request and process image
$intRequest->handleRequest($request);

// getResponse returns a Symfony\Component\HttpFoundation\Response object
// with image mime-type and data. All you need is to send it!
return $intRequest->getResponse($request);

使用URL重写

如果您想使用干净的 URL,您可以添加 ShortUrlExpander 类来监听缩短的 URL,如:https://:8888/intervention-request/f100x100-g/images/testPNG.png

首先,添加一个 .htaccess 文件(或其 Nginx 相当物)来激活重新编写。

# .htaccess
# Pretty URLs
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [S=40]
RewriteRule . index.php [L]
</IfModule>

然后,在处理 InterventionRequest 之前,将这些行添加到您的应用程序中。 ShortUrlExpander 将在您的现有 $request 对象上工作。

use AM\InterventionRequest\ShortUrlExpander;
/*
 * Handle short url with Url rewriting
 */
$expander = new ShortUrlExpander($request);
// Enables using /cache in request path to mimic a pass-through file serve.
//$expander->setIgnorePath('/cache');
$params = $expander->parsePathInfo();
if (null !== $params) {
    // this will convert rewritten path to request with query params
    $expander->injectParamsToRequest($params['queryString'], $params['filename']);
}

快捷方式

可以使用 -(破折号)字符组合 URL 短路。例如,f100x100-q50-g1-p0 代表 fit=100x100&quality=50&greyscale=1&progressive=0

使用透明缓存

干预请求可以将您的图像保存到公共文件夹,以便在生成后由 ApacheNginx 提供服务。这可以减少 首次字节时间,因为不再调用 PHP。

  • 确保在将请求代理到 PHP 之前,您已配置 ApacheNginx 来提供真实文件。否则可能会导致文件覆盖!
  • 如果使用 ShortUrlExpander 来模拟不带任何查询字符串的真实图像路径,则透传缓存才可用。
  • 您的缓存文件夹 必须 是公开的(在您的文档根目录下),这样任何人都可以看到您的文档。如果您的图像必须通过 PHP 防火墙进行保护,则不应激活 透传 缓存。
  • 垃圾收集器将不会调用,因为缓存图像将不再由您的 PHP 服务器提供,而是由 ApacheNginx 提供。
  • 透传缓存将首次在请求中使用的真实路径上保存图像,确保它不会覆盖任何应用程序文件。

将配置缓存路径定义为公共文件夹。

$conf = new Configuration();
$conf->setCachePath(APP_ROOT . '/cache');
$conf->setUsePassThroughCache(true);

然后启用 ShortUrlExpander忽略您的缓存路径,以仅处理路径信息。

$expander = new ShortUrlExpander($request);
// Enables using /cache in request path to mimic a pass-through file serve.
$expander->setIgnorePath('/cache');

转换为webp

确保您的 PHP 已编译 WebP 图像格式。

Intervention Request 可以通过向现有图像文件追加 .webp 来自动生成 WebP 图像。

对于 /image.jpg 文件,使用 /image.jpg.webp

Intervention Request 将查找没有 .webp 扩展名的图像文件,如果不存在则抛出 404 错误。

强制垃圾收集

使用命令行

bin/intervention gc:launch /path/to/my/cache/folder --log /path/to/my/log/file.log

扩展 Intervention Request

Intervention Request 使用 处理器 来修改原始图像。默认情况下,每个可用的操作都由一个继承自 AbstractProcessor 的类(查看 src/Processor 文件夹)处理。

您可以创建自己的 处理器 并通过向您的 InterventionRequest 对象注入一个数组来覆盖默认的处理器。

/*
 * Handle main image request with a
 * custom list of Processors.
 */
$iRequest = new InterventionRequest(
    $conf,
    $fileResolver,
    $log,
    [
        new Processor\WidenProcessor(),
        // add or replace with your own Processors
    ]
);

请注意,处理器 在此数组中的位置非常重要,请参阅 InterventionRequest.php 类中的默认处理器。调整大小处理器应该是第一个,质量处理器应该是最后一个,因为图像操作将按照您处理器的顺序执行。

添加自定义事件订阅者

如果您需要在图像提供服务之前对其进行优化/修改,可以创建自定义操作,使用 ImageSavedEventSymfony 事件系统。

创建一个实现 ImageEventSubscriberInterface 的类,并例如监听 ImageSavedEvent::NAME

public static function getSubscribedEvents()
{
    return [
        ImageSavedEvent::class => 'onImageSaved',
    ];
}

此事件将携带一个包含所有您需要优化/修改内容的 ImageSavedEvent 对象。然后,使用 $interventionRequest->addSubscriber($yourSubscriber) 方法来注册它。

可用事件

监听器示例

  • WatermarkListener 将在您的图像上打印文本。
  • KrakenListener 将使用 kraken.io 外部服务优化您的图像文件。
  • TinifyListener 将使用 tinyjpg.com 外部服务优化您的图像文件。
  • JpegTranListener 将使用本地的 jpegtran 二进制文件优化您的图像文件。

当然,您可以构建自己的监听器并与我们分享!

性能

如果您的 Intervention-request 抛出类似错误

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 5184 bytes).

这是因为您正在尝试处理一个过大的图像。解决方案是增加您的 memory_limit PHP 设置,超过 256M。您可以在服务器的 php.ini 文件中编辑此文件。

如果您的托管计划允许您动态更改 PHP 配置,您可以在 index.php 文件中使用 ini_set('memory_limit', '256M');

一般来说,我们鼓励您在使用 Intervention-request 之前始终降低您原始图像的大小。

优化

jpegoptim

如果您在服务器上安装了 jpegoptim,您可以将其添加到您的配置中。

$conf->setJpegoptimPath('/usr/local/bin/jpegoptim');

pngquant

如果您在服务器上安装了 pngquant,您可以将其添加到您的配置中。

$conf->setPngquantPath('/usr/local/bin/pngquant');
$conf->setLossyPng(true); // use palette lossy png compression - default: false

oxipng

如果您在服务器上安装了 oxipng,您可以将其添加到您的配置中。

$conf->setOxipngPath('/usr/local/bin/oxipng');

pingo

如果您在服务器上安装了 pingoWine,您可以将其添加到配置中。

$conf->setPingoPath('/usr/local/bin/pingo.exe');
$conf->setLossyPng(true); // use palette lossy png compression - default: false
$conf->setNoAlphaPingo(true); // Remove png transparency to compress more - default: false

kraken.io

如果您订阅了付费的 kraken.io 计划,您可以添加专门的 KrakenListener 以将缩放后的图片发送到外部服务。

$iRequest->addSubscriber(new \AM\InterventionRequest\Listener\KrakenListener(
    'your-api-key', 
    'your-api-secret', 
    true,
    $log
));

请注意,图片将通过 kraken.io API 发送,这将需要额外的时间。

tinyjpg.com

如果您订阅了付费的 tinyjpg.com 计划,您可以添加专门的 TinifyListener 以将缩放后的图片发送到外部服务。

$iRequest->addSubscriber(new \AM\InterventionRequest\Listener\TinifyListener(
    'your-api-key',
    $log
));

请注意,图片将通过 kraken.io API 发送,这将需要额外的时间。

jpegtran

如果您想使用系统中的 jpegtranMozjpeg,您可以使用 JpegTranListener

$iRequest->addSubscriber(new \AM\InterventionRequest\Listener\JpegTranListener(
    '/usr/local/opt/mozjpeg/bin/jpegtran',
    $log
));

优化基准

默认质量为 90%。
AVIF 转换仅支持自定义编译的 ImageMagick,并且仅支持无损编码。

许可证

Intervention RequestAmbroise Maupate 精心制作,遵循 MIT 许可证

祝您玩得开心!

测试

index.php 复制到 dev.php,然后使用 router.php 作为路由器启动 PHP 服务器命令。

php -S 0.0.0.0:8088 -t web router.php 

然后在浏览器中打开 http://0.0.0.0:8088/dev.php/w300/rhino.jpg。您应该能够测试启用 ShortUrlintervention-request

如果您想测试 pass-through 缓存,取消注释 dev.php 中的第 46 和 56 行,然后打开 http://0.0.0.0:8088/dev.php/cache/w300/rhino.jpg。第一次请求将由 PHP 处理(查看响应头),然后后续请求将直接由您的服务器处理(不再有 Intervention Request 头部)。