图片走OSS实时压缩:本地存储不变,OSS取图带 x-oss-process #56

Open
opened 2026-11-05 05:04:30 +00:00 by laoyang · 0 comments
Owner

图片走 OSS 实时压缩:本地存储不管,OSS 存储取图时带 x-oss-process

用户需求(2026-11-05)

「图片的压缩采用OSS方式,也就是说,如果图片是放在本地服务器的,
也就是传到Upload这样的文件夹里面的,就不管它。
如果是传到OSS里面的,你到网上查一下:OSS在获取图片的时候,
好像可以传一个参数,它会给你返回一张压缩过的图片文件。
好像我记得有这么一个功能或者参数,你去查一下。如果可行的话,
就用OSS的压缩就行了。」

查证结果:功能确实存在

阿里云 OSS 图片处理(IMG),取图时在 URL 后加 x-oss-process:

https://bucket.endpoint/object.jpg?x-oss-process=image/resize,w_400/quality,q_85

支持的常用操作:

操作 参数 说明
缩放 resize,w_400 / resize,l_1200 宽 / 长边(等比)
质量 quality,q_85 JPEG/WebP 质量 1-100
格式 format,webp 转 WebP(体积再降 25-35%)
渐进 interlace,1 渐进式 JPEG

要点:

  • 实时处理,不占存储 —— 原图不动,只改返回内容
  • 目标尺寸大于原图时默认返回原图(不会放大),除非加 limit_0
  • 私有桶需要把 x-oss-process 计入签名(canonical resource 追加 ?x-oss-process=...)

现状分析(本项目)

环节 现状 问题
OssDriver::get() 支持 $extra,但那是请求头 x-oss-process 是 query 参数,且要参与签名
OssDriver::authorization() 签名只拼 /{bucket}/{key} 加 process 后签名会失败(403)
media.php 取到图片后 cacheLocally() 回写完整原图 加了压缩后,缓存里存的是压缩版;不同尺寸请求会互相覆盖

⇒ 三处都要改,缺一个都会出错。

设计

① OSS 驱动:支持 query 参数并计入签名

public function get(string $key, array $extra = [], string $process = ''): array
  • $process 非空时,URL 追加 ?x-oss-process=<process>
  • 签名用 canonicalResource = /{bucket}/{key}?x-oss-process=<process>
    (OSS 规范:子资源参数才计入签名;x-oss-process 属于此类)

② Storage 门面:透传 process,且只对 OSS 生效

public static function read(int $familyId, string $key, string $process = ''): array
  • $process 为空 ⇒ 原行为
  • 驱动是 local ⇒ 忽略 $process(用户:"本地的不不管它")
  • 驱动是 oss ⇒ 透传

③ media.php:按尺寸分不同缓存键

现在的 cacheLocally($key, $body) 会把压缩版写到原 key 的本地路径,
之后所有请求都拿到这个尺寸 —— 必须改:

缓存路径 = uploads/_proc/<w>/<原key>     # 有 process 时
         = uploads/<原key>               # 无 process(原图)

⚠️ 原图(无 process)仍然缓存 —— 它是最通用的,且下载要用原图。
⚠️ 压缩版缓存不加进数据库,纯磁盘缓存,可随时删。

尺寸档位

不做无限档(每档都要占缓存)。按实际用法定三档:

用途 参数 缓存键
缩略图(列表/照片墙) resize,l_400/quality,q_80 _proc/400/{key}
详情大图(点开看) resize,l_1600/quality,q_85 _proc/1600/{key}
原图(下载/原尺寸) 无 原 key

验收

  • 本地存储的图片行为完全不变
  • OSS 图片带 x-oss-process 请求返回压缩版(体积明显变小)
  • 签名正确(不报 403)
  • 原图仍可下载(无 process)
  • 不同尺寸不互相覆盖缓存

风险

⚠️ x-oss-process 计费:按处理次数收费(约 ¥0.0005/次)。
有本地缓存后,同一张图同一尺寸只处理一次,量不大。
⚠️ 桶必须开启「图片处理」服务(多数默认开启,私有桶也支持)。


为什么单独建单

#57 是视频转码(H.265→H.264,必须落盘转);本单是图片取图时实时压缩(不动原图,OSS 侧处理)。两者都涉及媒体体积,但机制完全不同。

# 图片走 OSS 实时压缩:本地存储不管,OSS 存储取图时带 x-oss-process ## 用户需求(2026-11-05) > 「图片的压缩采用OSS方式,也就是说,如果图片是放在本地服务器的, > 也就是传到Upload这样的文件夹里面的,就不管它。 > 如果是传到OSS里面的,你到网上查一下:OSS在获取图片的时候, > 好像可以传一个参数,它会给你返回一张压缩过的图片文件。 > 好像我记得有这么一个功能或者参数,你去查一下。如果可行的话, > 就用OSS的压缩就行了。」 ## 查证结果:功能确实存在 阿里云 OSS **图片处理**(IMG),取图时在 URL 后加 `x-oss-process`: ``` https://bucket.endpoint/object.jpg?x-oss-process=image/resize,w_400/quality,q_85 ``` 支持的常用操作: | 操作 | 参数 | 说明 | |---|---|---| | 缩放 | `resize,w_400` / `resize,l_1200` | 宽 / 长边(等比) | | 质量 | `quality,q_85` | JPEG/WebP 质量 1-100 | | 格式 | `format,webp` | 转 WebP(体积再降 25-35%) | | 渐进 | `interlace,1` | 渐进式 JPEG | 要点: - **实时处理,不占存储** —— 原图不动,只改返回内容 - **目标尺寸大于原图时默认返回原图**(不会放大),除非加 `limit_0` - 私有桶需要把 `x-oss-process` **计入签名**(canonical resource 追加 `?x-oss-process=...`) ## 现状分析(本项目) | 环节 | 现状 | 问题 | |---|---|---| | `OssDriver::get()` | 支持 `$extra`,但那是**请求头** | `x-oss-process` 是 **query 参数**,且要参与签名 | | `OssDriver::authorization()` | 签名只拼 `/{bucket}/{key}` | 加 process 后签名会失败(403) | | `media.php` | 取到图片后 `cacheLocally()` **回写完整原图** | 加了压缩后,缓存里存的是压缩版;不同尺寸请求会互相覆盖 | ⇒ 三处都要改,缺一个都会出错。 ## 设计 ### ① OSS 驱动:支持 query 参数并计入签名 ```php public function get(string $key, array $extra = [], string $process = ''): array ``` - `$process` 非空时,URL 追加 `?x-oss-process=<process>` - **签名用** `canonicalResource = /{bucket}/{key}?x-oss-process=<process>` (OSS 规范:子资源参数才计入签名;`x-oss-process` 属于此类) ### ② Storage 门面:透传 process,且**只对 OSS 生效** ```php public static function read(int $familyId, string $key, string $process = ''): array ``` - `$process` 为空 ⇒ 原行为 - 驱动是 `local` ⇒ **忽略 `$process`**(用户:"本地的不不管它") - 驱动是 `oss` ⇒ 透传 ### ③ media.php:按尺寸分不同缓存键 现在的 `cacheLocally($key, $body)` 会把压缩版写到**原 key 的本地路径**, 之后所有请求都拿到这个尺寸 —— 必须改: ``` 缓存路径 = uploads/_proc/<w>/<原key> # 有 process 时 = uploads/<原key> # 无 process(原图) ``` ⚠️ **原图(无 process)仍然缓存** —— 它是最通用的,且下载要用原图。 ⚠️ 压缩版缓存**不加进数据库**,纯磁盘缓存,可随时删。 ## 尺寸档位 不做无限档(每档都要占缓存)。按实际用法定三档: | 用途 | 参数 | 缓存键 | |---|---|---| | 缩略图(列表/照片墙) | `resize,l_400/quality,q_80` | `_proc/400/{key}` | | 详情大图(点开看) | `resize,l_1600/quality,q_85` | `_proc/1600/{key}` | | 原图(下载/原尺寸) | 无 | 原 key | ## 验收 - [ ] 本地存储的图片行为**完全不变** - [ ] OSS 图片带 `x-oss-process` 请求返回压缩版(体积明显变小) - [ ] 签名正确(不报 403) - [ ] 原图仍可下载(无 process) - [ ] 不同尺寸不互相覆盖缓存 ## 风险 ⚠️ `x-oss-process` 计费:**按处理次数收费**(约 ¥0.0005/次)。 有本地缓存后,同一张图同一尺寸只处理一次,量不大。 ⚠️ 桶必须开启「图片处理」服务(多数默认开启,私有桶也支持)。 --- ### 为什么单独建单 #57 是视频转码(H.265→H.264,必须落盘转);本单是图片取图时实时压缩(不动原图,OSS 侧处理)。两者都涉及媒体体积,但机制完全不同。
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/FamilyBook#56