Files
nl-admin-api/app/Service/common/upload/AliyunStorageService.php
2026-08-10 18:32:06 +08:00

77 lines
2.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Service\common\upload;
use App\BaseApp\BaseNotAuthService;
use App\Service\common\oss\OssStorageInterface;
use App\Service\common\UtilsService;
use Illuminate\Support\Facades\Http;
/**
* 阿里云 OSSREST PutObjectAuthorization 签名)
*/
class AliyunStorageService extends BaseNotAuthService implements OssStorageInterface
{
protected array $config = [];
public function withConfig(array $config): static
{
$this->config = $config;
return $this;
}
public function uploadImage($filePath, string $key): bool|array
{
return $this->uploadFile($filePath, $key);
}
public function uploadVideo($filePath, string $key): bool|array
{
return $this->uploadFile($filePath, $key);
}
/**
* 使用 OSS V1 签名上传对象
*/
private function uploadFile($filePath, string $key): bool|array
{
$accessKey = (string) ($this->config['access_key'] ?? '');
$secretKey = (string) ($this->config['secret_key'] ?? '');
$bucket = (string) ($this->config['bucket'] ?? '');
$endpoint = (string) ($this->config['endpoint'] ?? '');
$domain = rtrim((string) ($this->config['domain'] ?? ''), '/');
if ($accessKey === '' || $secretKey === '' || $bucket === '' || $endpoint === '') {
UtilsService::getInstance()->errorThrow('阿里云 OSS 配置不完整(需要 AccessKey/Secret/Bucket/Endpoint');
}
$prefix = trim((string) ($this->config['path_prefix'] ?? ''), '/');
if ($prefix !== '' && !str_starts_with($key, $prefix . '/')) {
$key = $prefix . '/' . ltrim($key, '/');
}
$path = is_object($filePath) && method_exists($filePath, 'getRealPath')
? $filePath->getRealPath()
: (string) $filePath;
$content = file_get_contents($path);
$contentType = 'application/octet-stream';
$date = gmdate('D, d M Y H:i:s \G\M\T');
$resource = '/' . $bucket . '/' . $key;
$stringToSign = "PUT\n\n{$contentType}\n{$date}\n{$resource}";
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $secretKey, true));
$host = preg_replace('#^https?://#', '', rtrim($endpoint, '/'));
// 支持传入 oss-cn-xxx.aliyuncs.com 或带 bucket 的域名
if (!str_starts_with($host, $bucket . '.')) {
$host = $bucket . '.' . $host;
}
$url = 'https://' . $host . '/' . $key;
$response = Http::withHeaders([
'Date' => $date,
'Content-Type' => $contentType,
'Authorization' => 'OSS ' . $accessKey . ':' . $signature,
])->withBody($content, $contentType)->put($url);
if (!$response->successful()) {
UtilsService::getInstance()->errorThrow('阿里云上传失败:' . $response->body());
}
$publicUrl = $domain !== '' ? ($domain . '/' . $key) : $url;
return ['key' => $key, 'url' => $publicUrl];
}
}