Files
lgp-admin-plus-api/app/Service/common/upload/ObjectKeyNormalizeTrait.php

76 lines
2.7 KiB
PHP
Raw Normal View History

<?php
namespace App\Service\common\upload;
/**
* 对象键规整
*
2026-08-19 08:16:49 +08:00
* 上传用 normalizeObjectKey可补 path_prefix
* 列举 / 删除用 normalizeListedKey只压斜杠用服务端真实 key
* 使用方需要有 $this->config OssRuntimeConfigService 注入,含 path_prefix / domain
*/
trait ObjectKeyNormalizeTrait
{
/**
2026-08-19 08:16:49 +08:00
* 压平重复斜杠,不补 path_prefix
*
* 列举结果必须走这里OSS 回的 key 就是对象真实路径。
* 若再套一层 path_prefix根目录的历史文件 b_xxx.jpg会被改写成
* uploads/b_xxx.jpg素材库入库地址全 404
*/
protected function normalizeListedKey(string $key): string
{
return ltrim((string) preg_replace('#/{2,}#', '/', trim($key)), '/');
}
/**
* 上传 / 删除用:缺 path_prefix 时补上,并压平重复斜杠
*
* 为什么必须压平uploads//spa/a.jpg 与 uploads/spa/a.jpg 在 OSS 上是两个对象,
* 但拼出来的访问地址会被 CDN 归一成同一个。素材库按 path 建索引,
* 不统一就会落成两条记录,回收删掉其中一条后另一条变成指向已删对象的幽灵。
*/
protected function normalizeObjectKey(string $key): string
{
2026-08-19 08:16:49 +08:00
$key = $this->normalizeListedKey($key);
if ($key === '') {
return '';
}
$prefix = trim((string) ($this->config['path_prefix'] ?? ''), '/');
if ($prefix !== '' && $key !== $prefix && !str_starts_with($key, $prefix . '/')) {
$key = $prefix . '/' . $key;
}
return $key;
}
/**
2026-08-19 08:16:49 +08:00
* 列举前缀:只认调用方传入的值,留空 = 扫整个 Bucket
*
2026-08-19 08:16:49 +08:00
* 以前空前缀会偷偷套配置里的 path_prefix。种子数据把七牛写成 uploads
* 而本站历史文件都在根目录b_*.jpg一拉就是空列表。
* 素材库文案也是「留空表示整个 Bucket」这里必须跟文案一致
* 要收窄范围请在同步抽屉里显式填前缀。
*/
protected function scopedListPrefix(string $prefix): string
{
2026-08-19 08:16:49 +08:00
return $this->normalizeListedKey($prefix);
}
/**
* 拼公开访问地址;未配置 domain 时回落到调用方给的默认地址
*/
protected function publicUrlOf(string $key, string $fallback = ''): string
{
$domain = rtrim((string) ($this->config['domain'] ?? ''), '/');
return $domain !== '' ? $domain . '/' . $key : $fallback;
}
/**
* 单页列举条数收口,避免上游把 limit 传成 0 或者十万
*/
protected function boundedLimit(int $limit): int
{
return max(1, min($limit, 1000));
}
}