图片走 OSS 实时压缩:取图带 x-oss-process,本地存储不受影响 (#56)
用户 2026-11-05:「如果图片是放在本地服务器的…就不管它。
如果是传到 OSS 里面的…就用 OSS 的压缩就行了。」
查证:OSS 图片处理确实存在,取图 URL 加 x-oss-process 即可实时压缩,
原图不动、不占额外存储。
三处改动(缺一个都会出错):
1. OssDriver
- get() 新增 $process 参数
- authorization() 新增 $subresource:x-oss-process 属于子资源,
必须计入 CanonicalizedResource,否则 403 SignatureDoesNotMatch
- URL 拼接带上 ?x-oss-process=...
2. Storage::read()
- 新增 $process,仅当驱动是 oss 时透传
- 本地驱动忽略(用户明确要求「本地不管它」)
- 带 process 时跳过"本地优先"缓存(那个缓存里是原图,
拿原图当压缩版返回等于压缩没生效)
3. media.php
- 新增 ?w= 参数,白名单三档 400/800/1600
- 按尺寸分档缓存到 _proc/<w>/<key>,避免互相覆盖
- 无 w 时行为完全不变(300+ 处既有 img 不受影响)
白名单而非透传的理由:OSS 图片处理按次计费,
放任 ?w= 任意值会让 ?w=1、?w=9999 这类请求把处理次数打上去。
实测(一张 6602 KB 的图):
原图 6602 KB
w=400 26 KB 省 99.6%
w=800 108 KB 省 98%
w=1600 468 KB 省 93%
应用位置(保守,先动最确定的):
_attachments.php 照片墙缩略图 → w=400
trips/show.php 行程题图 → w=1600
下载链接一律不加 w(用户要原文件,不能偷偷降质)
This commit is contained in:
+36
-6
@@ -153,14 +153,44 @@ final class Storage
|
||||
* 从本地搬到云端(或反过来)时,历史文件可能只在一边,
|
||||
* 本地优先能保证迁移期的老文件照样打得开,也让回滚随时可行。
|
||||
*/
|
||||
public static function read(int $familyId, string $key): array
|
||||
/**
|
||||
* 读一个对象。
|
||||
*
|
||||
* @param string $process OSS 图片处理参数(如 `image/resize,l_400/quality,q_80`)。
|
||||
*
|
||||
* 🔴 #56(用户 2026-11-05):「如果图片是放在本地服务器的…就不管它。
|
||||
* 如果是传到 OSS 里面的…就用 OSS 的压缩就行了。」
|
||||
*
|
||||
* ## 两种驱动下的行为
|
||||
*
|
||||
* | 驱动 | `$process` 非空时 |
|
||||
* |---|---|
|
||||
* | `oss` | 透传给 `OssDriver::get()` ⇒ OSS 实时压缩 |
|
||||
* | `local` | **忽略** —— 本地没有图片处理服务,不该假装有 |
|
||||
*
|
||||
* ⚠️ 带 `$process` 时**跳过本地缓存**:那个缓存里是**原图**,
|
||||
* 拿原图当压缩版返回,等于压缩没生效而且用户以为生效了。
|
||||
* (缓存由 media.php 自己按尺寸分目录管理,见那里的说明。)
|
||||
*/
|
||||
public static function read(int $familyId, string $key, string $process = ''): array
|
||||
{
|
||||
$local = FB_UPLOADS . '/' . ltrim($key, '/');
|
||||
if ($key !== '' && is_file($local)) {
|
||||
$body = (string)@file_get_contents($local);
|
||||
return ['ok' => true, 'status' => 200, 'headers' => [], 'body' => $body, 'error' => '', 'from' => 'local'];
|
||||
/* 只有无 process 时才走"本地优先":原图有缓存就直接读,
|
||||
省掉整个 OSS round-trip。带 process 的必须去 OSS 要压缩版。 */
|
||||
if ($process === '') {
|
||||
$local = FB_UPLOADS . '/' . ltrim($key, '/');
|
||||
if ($key !== '' && is_file($local)) {
|
||||
$body = (string)@file_get_contents($local);
|
||||
return ['ok' => true, 'status' => 200, 'headers' => [], 'body' => $body,
|
||||
'error' => '', 'from' => 'local'];
|
||||
}
|
||||
}
|
||||
return self::disk($familyId)->get($key);
|
||||
|
||||
$disk = self::disk($familyId);
|
||||
/* 本地驱动不支持图片处理 ⇒ 忽略 process(用户明确要求"本地不管它") */
|
||||
if ($process === '' || $disk->id() !== 'oss') {
|
||||
return $disk->get($key);
|
||||
}
|
||||
return $disk->get($key, [], $process);
|
||||
}
|
||||
|
||||
public static function exists(int $familyId, string $key): bool
|
||||
|
||||
Reference in New Issue
Block a user