首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Laravel 整合阿里雲 OSS Composer 包:johnlui/aliyun-oss 使用完整指南

     編輯:PHP 相關知識

阿里雲 OSS (Object Storage Service) 是雲端物件儲存服務。Laravel 官方不內建 OSS 驅動,社區優秀封裝 johnlui/aliyun-oss 提供簡潔的 API。本文詳解安裝、配置、上傳、下載、簽名 URL、多 Bucket、錯誤處理與生產級最佳實踐。

安裝

composer require johnlui/aliyun-oss

支援 Laravel 5.5+ 自動發現 ServiceProvider。Laravel 5.4 需手動註冊:

// config/app.php
'providers' => [
    JohnLui\AliyunOSS\AliyunOSSServiceProvider::class,
],
'aliases' => [
    'OSS' => JohnLui\AliyunOSS\Facades\AliyunOSS::class,
]

配置

# .env
OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com
OSS_ACCESS_KEY_ID=your_access_key_id
OSS_ACCESS_KEY_SECRET=your_access_key_secret
OSS_BUCKET=your-bucket-name
OSS_CDN_DOMAIN=cdn.yourdomain.com # 可選:自定義 CDN 域名

# config/filesystems.php (可選整合到 Flysystem)
'disks' => [
    'oss' => [
        'driver' => 'oss',
        'endpoint' => env('OSS_ENDPOINT'),
        'access_key_id' => env('OSS_ACCESS_KEY_ID'),
        'access_key_secret' => env('OSS_ACCESS_KEY_SECRET'),
        'bucket' => env('OSS_BUCKET'),
    ],
]

基礎用法

1. Facade 靜態呼叫 (最簡單)

use OSS;

// 上傳檔案
$result = OSS::uploadFile('avatars/user_1.jpg', storage_path('app/public/avatar.jpg'));
// $result = ['url' => 'https://bucket.oss-cn-hangzhou.aliyuncs.com/avatars/user_1.jpg', ...]

// 上傳字串內容
OSS::uploadContent('config/app.json', '{"debug": true}');

// 獲取簽名 URL (私有桶臨時授權)
$signedUrl = OSS::signUrl('private/report.pdf', '+10 minutes'); // 10 分鐘有效

// 刪除檔案
OSS::deleteObject('old/temp.jpg');

// 判斷存在
if (OSS::objectExists('avatars/user_1.jpg')) { ... }

// 獲取檔案元資料
$meta = OSS::getObjectMeta('avatars/user_1.jpg');
// ['content-length', 'content-type', 'last-modified', 'etag', ...]

2. 依賴注入服務實例 (可測試、多 Bucket)

use JohnLui\AliyunOSS\AliyunOSS;

class AvatarService
{
    protected AliyunOSS $oss;
    
    public function __construct(AliyunOSS $oss)
    {
        $this->oss = $oss->setBucket(config('filesystems.disks.oss.bucket'));
    }
    
    public function upload(UploadedFile $file, int $userId): string
    {
        $key = "avatars/user_{$userId}_" . time() . '.' . $file->getClientOriginalExtension();
        $this->oss->uploadFile($key, $file->getPathname());
        return $this->oss->getUrl($key); // 公開讀取 URL
    }
    
    public function getSignedUrl(string $key, int $minutes = 60): string
    {
        return $this->oss->getUrl($key, now()->addMinutes($minutes));
    }
}

進階功能

1. 分片上傳 (大檔案 > 100MB)

// 手動分片上傳 (SDK 內部已封裝 multipart upload)
$oss->uploadFile('large/video.mp4', '/path/to/large/video.mp4', [
    'partSize' => 10 * 1024 * 1024, // 10MB 分片
    'concurrency' => 3,
    'progress' => function ($bytes, $total) {
        echo "Progress: " . round($bytes / $total * 100, 2) . "%\n";
    }
]);

2. 圖片處理參數 (IMG 服務)

// 原圖處理參數
$processedUrl = $oss->getUrl('images/photo.jpg') . '?x-oss-process=image/resize,w_300,h_200/quality,q_80/format,webp';
// 等同:https://bucket.oss-cn-hangzhou.aliyuncs.com/images/photo.jpg?x-oss-process=image/resize,w_300,h_200/quality,q_80/format,webp

// 樣式分隔符 (需 OSS 控制台建立樣式)
$styleUrl = $oss->getUrl('images/photo.jpg') . '!thumbnail';

3. 表單直傳 (瀏覽器直傳 OSS,減輕應用伺服器壓力)

// 後端生成 Policy + Signature
$policy = $oss->getPolicy([
    'expiration' => now()->addMinutes(30)->toISOString(),
    'conditions' => [
        ['content-length-range', 0, 10 * 1024 * 1024], // 限制 10MB
        ['starts-with', '$key', 'uploads/user_123/'],
    ],
]);
// 返回給前端:policy (base64), signature, access_key_id, endpoint, bucket, key 前綴

4. 事件通知 (OSS 觸發函數計算/隊列)

// 控制台配置:ObjectCreated -> HTTP 回調到你的 API
// 回調驗證
$auth = request()->header('Authorization');
$body = request()->getContent();
// 驗證簽名...
// 異步處理:轉碼、縮圖、入庫...

錯誤處理與重試

use OSS\Core\OssException;

try {
    $url = OSS::uploadFile('test.jpg', $path);
} catch (OssException $e) {
    // $e->getMessage() 包含 HTTP 狀態碼、OSS 錯誤碼、RequestId
    // 常見錯誤碼:
    // NoSuchBucket, AccessDenied, InvalidAccessKeyId, SignatureDoesNotMatch
    // RequestTimeTooSkewed (時間不同步), EntityTooLarge (>5GB)
    Log::error('OSS Upload Failed', [
        'error' => $e->getMessage(),
        'code' => $e->getCode(),
        'request_id' => $e->getRequestId(),
    ]);
    
    // 可重試邏輯 (網路抖動、5xx)
    if (in_array($e->getCode(), ['RequestTimeout', 'InternalError', '503'])) {
        // 指數退避重試...
    }
    
    throw $e;
}

多 Bucket / 多區域切換

// 動態切換 Bucket
$oss = OSS::boot($endpoint, $keyId, $keySecret);
$oss->setBucket('bucket-a')->uploadFile('a.txt', $pathA);
$oss->setBucket('bucket-b')->uploadFile('b.txt', $pathB);

// 或建立多個實例
$ossA = new AliyunOSS($endpointA, $keyId, $keySecret)->setBucket('bucket-a');
$ossB = new AliyunOSS($endpointB, $keyId, $keySecret)->setBucket('bucket-b');

整合 Laravel Flysystem (統一檔案系統抽象)

// composer require league/flysystem-aws-s3-v3 (OSS 兼容 S3 API)
// config/filesystems.php
'oss' => [
    'driver' => 's3',
    'key' => env('OSS_ACCESS_KEY_ID'),
    'secret' => env('OSS_ACCESS_KEY_SECRET'),
    'region' => 'oss-cn-hangzhou', // 非標準 region,但需填寫
    'bucket' => env('OSS_BUCKET'),
    'endpoint' => env('OSS_ENDPOINT'),
    'url' => env('OSS_CDN_DOMAIN'), // CDN 域名
    'visibility' => 'public',
],

// 使用
Storage::disk('oss')->put('file.txt', 'content');
Storage::disk('oss')->url('file.txt');

生產環境最佳實踐清單

項目建議
權限最小化RAM 子帳號僅授予特定 Bucket 的 PutObject/GetObject/DeleteObject
HTTPS 強制Endpoint 使用 https://,CDN 全站 HTTPS
防盜鏈OSS 控制台配置 Referer 白名單
生命週期規則自動轉冷存儲/刪除臨時檔案
跨域 (CORS)直傳需配置 AllowedOrigin, AllowedMethod, AllowedHeader, ExposeHeader: ETag
監控告警關注:請求失敗率、延遲 P99、流量計費、儲存量增長
備份策略跨區域複制 (CRR) 至備份 Bucket
時間同步伺服器啟用 NTP,避免 RequestTimeTooSkewed

常見問題 FAQ

上傳報 SignatureDoesNotMatch
檢查 AccessKey/Secret 正確性、系統時間同步、Endpoint 與 Bucket 區域匹配
上傳大檔案超時
調大 PHP max_execution_time、Nginx client_max_body_size、啟用分片上傳
簽名 URL 失效快
預設 10 分鐘,需業務層動態生成,不可靜態存儲
刪除不存在物件報錯
預設不拋錯,若需嚴格可捕獲 NoSuchKey

johnlui/aliyun-oss 以極簡 API 封裝了阿里雲 OSS SDK 核心功能,適合中小型專案快速接入。大型專案或需深度定製 (自定義重試、簽名 V4、VPC 專線) 時,建議直接使用官方 aliyuncs/oss-sdk-php。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved