图片走 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:
@@ -41,6 +41,28 @@ function media_fail(int $code, string $message): void
|
||||
}
|
||||
|
||||
$key = (string)($_GET['k'] ?? '');
|
||||
|
||||
/* 🔴 #56(用户 2026-11-05):「OSS在获取图片的时候,好像可以传一个参数,
|
||||
它会给你返回一张压缩过的图片文件…如果可行的话,就用OSS的压缩就行了。」
|
||||
|
||||
`?w=400` ⇒ 让 OSS 实时返回压缩版(`x-oss-process=image/resize,l_400`)。
|
||||
|
||||
⚠️ **白名单**而不是透传:OSS 图片处理**按次计费**(约 ¥0.0005/次),
|
||||
若放任 `?w=` 任意值,`?w=1`、`?w=9999` 这种请求会让处理次数暴涨。
|
||||
只允许下面这几档 —— 覆盖实际用途,且数量可控。
|
||||
⚠️ 不带 `w` ⇒ 原图,**行为完全不变**(300+ 处既有 `<img>` 不受影响)。
|
||||
⚠️ 本地存储的图片:OSS 档位参数**自动失效**(Storage::read 里判驱动),
|
||||
用户明确要求「本地的不不管它」。 */
|
||||
$imgW = (int)($_GET['w'] ?? 0);
|
||||
/** 允许的尺寸档位 ⇒ OSS 处理参数 */
|
||||
$OssSizes = [
|
||||
400 => 'image/resize,l_400/quality,q_80',
|
||||
800 => 'image/resize,l_800/quality,q_82',
|
||||
1600 => 'image/resize,l_1600/quality,q_85',
|
||||
];
|
||||
if (!array_key_exists($imgW, $OssSizes)) {
|
||||
$imgW = 0; // 非法值一律按原图处理
|
||||
}
|
||||
$stageTok = (string)($_GET['stage'] ?? '');
|
||||
|
||||
/*
|
||||
@@ -162,14 +184,17 @@ if ($isImageKey) {
|
||||
}
|
||||
}
|
||||
|
||||
$res = Storage::read($familyId, $key);
|
||||
$res = Storage::read($familyId, $key, $imgW > 0 ? $OssSizes[$imgW] : '');
|
||||
$status = (int)($res['status'] ?? 0);
|
||||
$body = (string)($res['body'] ?? '');
|
||||
|
||||
// 远程取到的图片回写本地(下一跳命中文件系统,省掉整个 OSS round-trip)
|
||||
/* 远程取到的图片回写本地(下一跳命中文件系统,省掉整个 OSS round-trip)
|
||||
🔴 #56:**按尺寸分档存** —— 否则 400/800/1600 三档会互相覆盖,
|
||||
用户看到的尺寸随机。原图($imgW=0)仍存原路径,行为不变。 */
|
||||
if ($isImageKey && !empty($res['ok']) && $status === 200
|
||||
&& ($res['from'] ?? '') !== 'local' && $body !== '') {
|
||||
Storage::cacheLocally($key, $body);
|
||||
$cacheKey = $imgW > 0 ? ('_proc/' . $imgW . '/' . $key) : $key;
|
||||
Storage::cacheLocally($cacheKey, $body);
|
||||
}
|
||||
|
||||
if (empty($res['ok']) || $status < 200 || $status >= 300) {
|
||||
|
||||
Reference in New Issue
Block a user