更新若干功能

This commit is contained in:
2026-08-19 08:16:49 +08:00
parent 4979bb83d2
commit 72bc6502eb
56 changed files with 3627 additions and 343 deletions

View File

@@ -21,12 +21,19 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
'path_prefix' => '',
];
/** 同一次请求里复用,避免每页列举都去 UC 查一遍区域 */
private ?\Qiniu\Storage\BucketManager $cachedBucketMgr = null;
private string $cachedBucketMgrKey = '';
/**
* 注入解密后的运行时配置
*/
public function withConfig(array $config): static
{
$this->config = array_merge($this->config, $config);
$this->cachedBucketMgr = null;
$this->cachedBucketMgrKey = '';
return $this;
}
@@ -54,14 +61,17 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
* 列举空间对象BucketManager::listFilesmarker 分页)
*
* 七牛只在还有下一页时才回 marker所以 marker 为空即等于列完了。
* 列举结果的 key 必须用服务端原值,不能再套 path_prefix
* 否则根目录历史文件会被改写成 uploads/b_xxx.jpg。
*/
public function listObjects(string $prefix = '', string $marker = '', int $limit = 100): array
{
$bucketMgr = $this->bucketManager();
$bucket = (string) ($this->config['bucket'] ?? '');
$listPrefix = $this->scopedListPrefix($prefix);
[$ret, $err] = $bucketMgr->listFiles(
$bucket,
$this->scopedListPrefix($prefix),
$listPrefix !== '' ? $listPrefix : null,
$marker !== '' ? $marker : null,
$this->boundedLimit($limit)
);
@@ -69,9 +79,19 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
UtilsService::getInstance()->errorThrow('七牛云列举对象失败:' . $this->errorText($err));
}
$ret = is_array($ret) ? $ret : [];
$rawItems = $ret['items'] ?? $ret['Items'] ?? [];
// 个别 SDK 版本成功时直接回文件数组,而不是 {items: [...]}
if ($rawItems === [] && isset($ret[0]) && is_array($ret[0])) {
$rawItems = $ret;
}
$items = [];
foreach ((array) ($ret['items'] ?? []) as $row) {
$key = $this->normalizeObjectKey((string) ($row['key'] ?? ''));
foreach ((array) $rawItems as $row) {
if (!is_array($row)) {
continue;
}
$key = $this->normalizeListedKey((string) ($row['key'] ?? ''));
if ($key === '' || str_ends_with($key, '/')) {
continue;
}
@@ -81,7 +101,7 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
'hash' => (string) ($row['hash'] ?? ''),
// putTime 的单位是 100 纳秒,当秒用会得到五亿年后的时间戳
'last_modified' => intdiv((int) ($row['putTime'] ?? 0), 10000000),
'url' => $this->publicUrlOf($key, $key),
'url' => $this->publicUrlOf($key),
];
}
@@ -95,7 +115,7 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
public function deleteObject(string $key): bool
{
return $this->deleteFile($this->normalizeObjectKey($key));
return $this->deleteFile($this->normalizeListedKey($key));
}
/**
@@ -135,30 +155,50 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
private function deleteFile(string $key): bool
{
if (!class_exists(\Qiniu\Auth::class)) {
return false;
}
$auth = new \Qiniu\Auth($this->config['access_key'], $this->config['secret_key']);
$bucketMgr = new \Qiniu\Storage\BucketManager($auth);
$err = $bucketMgr->delete($this->config['bucket'], $key);
$err = $this->bucketManager()->delete((string) $this->config['bucket'], $key);
return $err === null;
}
/**
* 构造 BucketManager顺手把「没装 SDK / 没填配置」两种情况前置拦掉
*
* 必须走 HTTPSSDK 默认 HTTP部分机房出网只放行 443,列举会直接空失败。
*/
private function bucketManager(): \Qiniu\Storage\BucketManager
{
if (!class_exists(\Qiniu\Auth::class)) {
UtilsService::getInstance()->errorThrow('未安装 qiniu/php-sdk请改用本地存储或安装依赖');
}
$accessKey = (string) ($this->config['access_key'] ?? '');
$secretKey = (string) ($this->config['secret_key'] ?? '');
$bucket = (string) ($this->config['bucket'] ?? '');
if ($accessKey === '' || $secretKey === '' || $bucket === '') {
UtilsService::getInstance()->errorThrow('七牛云配置不完整');
$accessKey = trim((string) ($this->config['access_key'] ?? ''));
$secretKey = trim((string) ($this->config['secret_key'] ?? ''));
$bucket = trim((string) ($this->config['bucket'] ?? ''));
$missing = [];
if ($accessKey === '') {
$missing[] = 'AccessKey';
}
return new \Qiniu\Storage\BucketManager(new \Qiniu\Auth($accessKey, $secretKey));
if ($secretKey === '') {
$missing[] = 'SecretKey';
}
if ($bucket === '') {
$missing[] = 'Bucket';
}
if ($missing !== []) {
UtilsService::getInstance()->errorThrow(
'七牛云配置不完整,缺少:' . implode('、', $missing) . '。请到「系统配置 → 存储」重新填写后保存'
);
}
$cacheKey = $accessKey . "\0" . $bucket;
if ($this->cachedBucketMgr !== null && $this->cachedBucketMgrKey === $cacheKey) {
return $this->cachedBucketMgr;
}
$sdkConfig = new \Qiniu\Config();
$sdkConfig->useHTTPS = true;
$this->cachedBucketMgr = new \Qiniu\Storage\BucketManager(
new \Qiniu\Auth($accessKey, $secretKey),
$sdkConfig
);
$this->cachedBucketMgrKey = $cacheKey;
return $this->cachedBucketMgr;
}
/**
@@ -167,7 +207,13 @@ class QiniuStorageService extends BaseNotAuthService implements OssStorageInterf
private function errorText(mixed $err): string
{
if (is_object($err) && method_exists($err, 'message')) {
return (string) $err->message();
$text = trim((string) $err->message());
if ($text !== '') {
return $text;
}
}
if (is_object($err) && method_exists($err, 'code')) {
return 'HTTP ' . $err->code();
}
if (is_object($err) || is_array($err)) {
return (string) json_encode($err, JSON_UNESCAPED_UNICODE);