escolalms / images
Escola 无头 LMS 图像处理
0.1.24
2024-02-14 13:58 UTC
Requires
- php: >=7.4
- escolalms/core: ^1
- escolalms/settings: ^0
- intervention/image: ^2
- intervention/imagecache: ^2
- laravel/framework: >=8.0
- spatie/laravel-image-optimizer: ^1.7.1
Requires (Dev)
- orchestra/testbench: >=5.0
- phpunit/phpunit: ^9.0
README
它做什么
该包通过给定参数从源创建调整大小的图像。这是一个无头方法,因此后端在前端请求之前不知道请求的大小。
输入图像由Laravel存储在任何可用的磁盘上(本地存储/s3/任何桶)。一旦请求调整大小的版本,就会创建并返回缓存的版本。以下是一些示例,以展示整体思路。
初始调整大小是通过Intervention/image使用GD
驱动程序完成的。这可以配置。
在初始调整大小之后,所有图像都使用image-optimizer进行优化。
为了获得最佳结果,必须安装二进制文件。EscolaLMS已准备好的Docker镜像可用于开发(标记work
)和生产(标记prod
)。
安装
composer require escolalms/images
php artisan migrate
数据库
image_caches
- 用于保存原始和调整大小图像路径的表
示例
默认。一个图像作为302
重定向结果。
基本的调整大小是通过URL API调用实现的,该调用重定向到新创建的文件。
示例 GET
调用
https:///api/images/img?path=test.jpg&w=100
调用应返回宽度为100px的调整大小图像- 检查文件是否存在
- 如果不存在,则使用可用库创建一个
- 返回302重定向
- 示例
https:///storage/imgcache/891ee133a8bb111497d494d4c91fe292d9d16bb3.jpg
(假设您正在使用本地磁盘存储,在s3位置的情况下,原始位置会有所不同)
一次性调整多个图像。结果为JSON数组。
示例 POST
调用如下
POST /api/images/img HTTP/1.1 Host: localhost:1000 Content-Type: application/json Content-Length: 212 { "paths": [{ "path": "tutor_avatar.jpg", "params": { "w": 100 } }, { "path": "tutor_avatar.jpg", "params": { "w": 200 } }, { "path": "tutor_avatar.jpg", "params": { "w": 300 } }] }
生成以下结果
[ { "url": "https:///storage/imgcache/3421584c40d270d0fa7ef0c31445a1565db07cb4.jpg", "path": "imgcache/3421584c40d270d0fa7ef0c31445a1565db07cb4.jpg", "hash": "3421584c40d270d0fa7ef0c31445a1565db07cb4" }, { "url": "https:///storage/imgcache/7efc528c2cc7b57d79a42f80d2c1891b517cabfe.jpg", "path": "imgcache/7efc528c2cc7b57d79a42f80d2c1891b517cabfe.jpg", "hash": "7efc528c2cc7b57d79a42f80d2c1891b517cabfe" }, { "url": "https:///storage/imgcache/5db4f572d8c8b1cb6ad97a3bffc9fd6c18b56cc3.jpg", "path": "imgcache/5db4f572d8c8b1cb6ad97a3bffc9fd6c18b56cc3.jpg", "hash": "5db4f572d8c8b1cb6ad97a3bffc9fd6c18b56cc3" } ]
哈希算法
存在一个简单的算法来猜测结果图像URL。这允许前端应用程序知道处理后的URL,而无需调用API。如下所示
$path = 'test.jpg'; $params = ['w'=>100]; $hash = sha1($path.json_encode($params));
则结果URL将是
$output_file = $url_prefix.$hash.$extension;
端点
测试
运行 ./vendor/bin/phpunit
来运行测试。
事件
此包扩展了filesystem
。
$this->app->extend('filesystem', function ($service, $app) {
return new CustomFilesystemManager($app);
});
FileDeleted
- 当您在Storage
外观中使用delete
方法时,将触发此事件。FileStored
- 当您使用put
、putFile
或putFileAs
方法时,将触发此事件。
监听器
此包监听FileDeleted
和FileStored
事件,并从给定路径删除调整大小的图像。
如何在前端使用此功能
以下是我们生成图像的完全无头方法
以下示例旨在实现两个目的
- 动态生成图片,前端决定需要什么尺寸
- 图片不是通过API提供
思路是,因为我们知道缓存的图片的哈希算法,我们可以猜测URL的格式。如果这个URL返回404错误,我们就调用API端点生成一张图片。幸运的是,这个端点创建所需的图片,将其缓存并返回重定向,这对于图片源来说是个好事情。
这种方法的重大缺点是,第一次用户在网络上可能会遇到404错误,并且在找不到图片后需要等待几秒钟才能渲染图片。
<script type="text/javascript" src="sha1.js"></script> <script> // Initial variables const imgPath = "tutor_avatar.jpg"; const imgPrefix = "https:///storage/imgcache"; const apiUrl = "https:///api/images/img"; const rndWith = Math.round(Math.random() * 1000); const params = { w: rndWith.toString() }; // random width params // super important that all param values are strings // hash from { w: 100 } is different then { w: "100" } // stright forward helper to convert obejct to URL query params const paramsToUrl = (params) => Object.entries(params) .map((e) => e.join("=")) .join("&"); /** * @param string path, example "tutor_avatar.jpg" * @param array params, example { w: "100" } or { w: "100", h: "10" } * @return Image */ const getImage = (path, params) => { const hash = SHA1(path + JSON.stringify(params)); const url = `${imgPrefix}/${hash}.${path.split(".").pop()}`; const imgApiUrl = `${apiUrl}/?path=${imgPath}&${paramsToUrl(params)}`; const image = new Image(); image.src = url; image.onerror = () => { if (image.src != imgApiUrl) { // the cached version does not exists yet, lets call API to create one and redirect. image.src = imgApiUrl; } }; return image; }; document.body.appendChild(getImage(imgPath, params)); </script>
工作示例可以在doc文件夹中找到。