因業務需要,AWS S3 不能使用了,要換成阿里雲OSS存儲和下載。簡單作以記錄,以作備忘。
1.參照https://help.aliyun.com/product/31815.html?spm=5176.2020520105.146.d500.30285e77DhksTQ 開通OSS服務並創建存儲空間,得到訪問的域名endpoint、AccessKeyID和AccessKeySecret;
2. 下載PC端ossbrowser工具,驗證bucket建立、文件創建、上傳和下載等基本操作,確保第1步正常;基於aws s3的大黃鴨CyberDuck訪問阿里雲oss bucket,總是報錯,應該是兩家工具不兼容;
3. 代碼移植
根據不同的開發語言,到https://help.aliyun.com/product/31815.html?spm=5176.2020520105.146.d500.30285e77DhksTQ的SDK參考中打開對應語言的頁面,如本例中是php的,頁面如https://help.aliyun.com/document_detail/32099.html?spm=5176.product31815.6.758.u4tuGR
3.a 下載最新的php sdk https://github.com/aliyun/aliyun-oss-php-sdk?spm=5176.doc32099.2.4.mSN0jX, 目前是2.2.4
3.b 構建本地php開發環境,修改SDK中sample下的Config.php,即第1步中的域名、ak/sk, 然後運行 SDK中 samples下的RunAll.php 即可看到各case都能正常運行
3.c 根據示例程序瞭解OSS API, 可以是這裏的例子 https://help.aliyun.com/document_detail/32101.html?spm=5176.doc32100.6.760.hd9tYF, 也可以是SDK中samples下的各個*.php,使用最多的是Object.php中的幾個接口。網頁中的一些接口描述尤其是返回值與samples中的有出入,最好是看samples中的代碼示例
3.d 把sdk放到應用的protected/extension/aliyun-oss目錄下,不用把SDK全部文件都放進去,只需要放src下的OSS目錄,及入口函數autoload.php即可,
即 aliyun-oss
------ autoload.php
------- OSS/***
3.e 代碼中遇到的問題及解決
3.e.1 file upload failed bucker_xx\/558be3c66aa2fda90452b6bc1acbd4d0
3.e.2 include(OssClient.php): failed to open stream:No such file or directory
3.e.3 "0:http body content is invalid: //// 上傳size 爲0的文件時,putObject會調用ossUtil::validateContent()對長度作判斷,允許0長度文件時可以去掉此判斷
\/OSS\/Core\/OssUtil.php:197:
\/OSS\/OssClient.php(978):OSS\\Core\\OssUtil::validateContent('''')\n
3.e.4 "ret":"0:上傳的文件不存在
3.e.5 Error[8]: Trying to get property of non-object
3.e.6 "ret":"0:NoSuchKey: The specified keydoes not exist. RequestId: 5A39DB1D6FF1C5510C4153AF
3.e.7 Error[2]:filesize(): stat failed for file to be downloaded
3.e.8 通過瀏覽器下載文件要增加
header('Content-Type: application/octet-stream');
header('Content-Disposition:
attachment; filename="'.$downloadName.'"');
針對各個問題,歸納起來原因,主要在於aws s3與aliyun oss的接口設計差異及返回值差異,相對來說,aws s3的接口設計及參數尤其返回值obj中包含的信息更詳細更完整些(如obj->header, obj->body等),aliyun oss的就相對簡單很多,返回的obj就是object的內容,不包含各種輔助信息。
具體實現的接口及調用接口:
getOssClient:
function getOssClient()
{
require_once ROOT_PATH.'/protected/extensions/aliyun-oss/autoload.php';
try {
$client = new \OSS\OssClient(Yii::app()->params['aliyun.oss.key'],Yii::app()->params['aliyun.oss.secret'],
Yii::app()->params['aliyun.oss.endpoint']); //endpoint即第1步中的域名
} catch (OssException $e) {
print $e->getMessage();
}
return $client;
}
if (!$client->doesBucketExist(self::OSS_BUCKET_NAME)) {
$ret = $client->createBucket(self::OSS_BUCKET_NAME, OssClient::OSS_ACL_TYPE_PRIVATE);
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
}catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
file_put_contents($destFile, $obj, FILE_APPEND); // getObject後在本地生成deskFile,可以再上傳或導出。
調用sample:
$client = getOssClient();
}
try {
$ret = $client->putObject(self::OSS_BUCKET_NAME, $objName, file_get_contents($filename));
try{
$obj = $client->getObject($bucket, $objName);
if(strlen($obj) > 0) {