顯示廣告
隱藏 ✕
看板 KnucklesNote
作者 Knuckles (站長 那克斯)
標題 [Linode] Object Storage 使用 AWS SDK for PHP
時間 2024-01-09 Tue. 04:11:45


[圖]


參考前一篇設定 Linode 的 Object Storage
[Linode] Object Storage 相容 S3 的檔案儲存空間 - KnucklesNote板 - Disp BBS

這篇記錄如何使用 PHP 存取 Object Storage 上的檔案

因為與 Amazon S3 相容,所以可以用 AWS SDK for PHP  
https://www.linode.com/docs/products/storage/object-storage/guides/aws-sdk-for-php/

要使用 AWS SDK,PHP 至少要有 5.5,如果自己下載 AWS SDK 的話,相依的套件會需要 PHP 7.2 才能執行,所以 PHP 5.6 的話要用 Composer 安裝才能解決相依問題, PHP 5.6 會安裝的版本為 aws/aws-sdk-php (3.278.3)

在專案目錄執行 composer 安裝 aws/aws-sdk-php
$ composer require aws/aws-sdk-php

裝好 AWS SDK 後,新增一個 test.php 檔
<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;

$config =
[
    'version' => 'latest',
    'region' => 'jp-osa-1',
    'endpoint' => 'https://jp-osa-1.linodeobjects.com/',
    'credentials' =>
    [
        'key' => '[access-key]',
        'secret' => '[secret-key]',
    ],
];

$client = new \Aws\S3\S3Client($config);
其中 region 和 endpoint 依照 cluster-url-s3-endpoint,選擇使用的 Data Center,
'region' 輸入 Cluster ID, 'endpoint' 輸入 Cluster URL
[access-key] 和 [secret-key] 換成在 Linode 控制台產生的 Access Key 和 Secret
[圖]
 

接著就能用物件 $client 存取 Bucket 中的檔案
// 列出 $bucket 裡面,開頭為 'test/' 的檔案
$bucket = 'disp';
$result = $client->listObjects(['Bucket' => $bucket, 'Prefix' => 'test/']);
foreach ($result['Contents'] as $object) {
    echo $object['Key'] . "\n";
}

// 上傳檔案 /path/to/logo.jpg 到 $bucket 的 test/logo.jpg
$path = '/path/to/logo.jpg';
$key = 'test/logo.jpg';
$client->putObject(['Bucket'=>$bucket, 'Key'=>$key, 'SourceFile'=>$path, 'ACL' => 'public-read']);

// 檢查檔案 $key 是否存在,回傳值為 Bool
$result = $client->doesObjectExist($bucket, $key);

// 下載 $bucket 的檔案 $key 存到 $path
$client->getObject(['Bucket'=>$bucket, 'Key'=>$key, 'SaveAs'=>$path);

// 刪除 $bucket 的檔案 $key
$client->deleteObject(['Bucket' => $bucket, 'Key' => $key]);

可以將其他要記錄的資訊寫在 Metadata
// 例如要再記錄圖檔的寬高
list($width, $height) = getimagesize($path);
$result = $client->putObject([
    'Bucket' => $bucket, 'Key' => $key, 'SourceFile' => $path, 'ACL' => 'public-read',
    'Metadata' => [ 'width' => $width, 'height' => $height ],
]);

// 只讀取檔案的資訊,不下載檔案
$result = $client->getObject(['Bucket' => $bucket, 'Key' => $key]);
$metadata = $result['Metadata'];
echo "size: ".$result['ContentLength']."\n"; // 等於 filesize($path)
$etag = str_replace('"', '', $result['ETag']); // 要去掉多餘的雙引號
echo "ETag: ".$etag."\n";  // 一般等於 md5_file($path),可用來檢查檔案是否相同
echo "filetype: ".$result['ContentType']."\n"; // image/jpeg
echo "width: ".$metadata['width']."\n";  // 圖檔的寬
echo "height: ".$metadata['height']."\n";  // 圖檔的高
$date = new DateTime($result['LastModified']); // 預設是UTC時間
$date->setTimezone(new DateTimeZone('Asia/Taipei'));
echo "LastModified: ".$date->format('Y-m-d H:i:s')."\n"; // 時區為台北的上傳時間

若上傳時想加上 md5 檢查檔案上傳的完整性,可加上 ContentMD5,參考 https://docs.aws.amazon.com/zh_tw/Am...#checking-object-integrity-md5
// 要使用 binary format 的 md5 再加上 base64_encode
$md5base64 = base64_encode(md5_file($path, true));
try{
    $result = $client->putObject([
        'Bucket' => $bucket,
        'Key'    => $key,
        'SourceFile' => $path,
        'ACL'    => 'public-read',
        'ContentMD5' => $md5base64,
    ]);
    echo "上傳成功\n";
}catch(Exception $e){
    echo "上傳失敗".$e->getMessage()."\n";
}
若驗證失敗會出現錯誤訊息 "400 Bad Request"
若檔案超過16MB被分割上傳的話不能用這個方法檢查

若上傳 s3 後想要刪掉主機上的檔案,可能會被上傳程序鎖定而無法馬上刪除,可以先將檔案內容讀到變數,然後上傳路徑 SourceFile 改為用內容 Body
$file = fopen($path, 'r');
$result = $s3client->putObject([
    'Bucket' => $s3_bucket,
    'Key'     => $key,
    'Body' => $file, //可以輸入檔案的 binary 或 resource
    'ACL'    => 'public-read',
    'Metadata' => [
        'width' => $width,
        'height' => $height,
    ],
]);
echo "上傳成功\n";
fclose($file);
unlink($path); // 刪除主機上的檔案
測試在 Windows 時才會鎖定,在 Linux 不會被鎖定用 SourceFile 即可


其他的功能可參考
https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html


--
※ 作者: Knuckles 時間: 2024-01-09 04:11:45 (台灣)
※ 看板: KnucklesNote 文章推薦值: 0 目前人氣: 0 累積人氣: 48 
分享網址: 複製 已複製
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇