php阿里雲oss-sdk上傳失敗情況處理
阿新 • • 發佈:2022-04-08
現象
oss上傳沒有成功,但是拿到了地址,導致訪問時返回404狀態碼
思路
我們先看自己寫的上傳oss部分程式碼
public function oss(string $file, string $object) { $ossClient = new OssClient($this->config['accessKeyId'], $this->config['accessKeySecret'], $this->config['endpoint']); $result = $ossClient->uploadFile($this->config['bucket'], ltrim($object, '/'), $file); return $result['oss-request-url']; }
按理說是由sdk返回的result
中拿到的地址,上傳失敗應該會直接丟擲異常
再看其中uploadFile
程式碼部分
public function uploadFile($bucket, $object, $file, $options = NULL)
{
// ...省略程式碼
$response = $this->auth($options);
$result = new PutSetDeleteResult($response);
return $result->getData();
}
其中主要方法是$this->auth($options)
private function auth($options) { // ...省略程式碼 try { $request->send_request(); } catch (RequestCore_Exception $e) { throw(new OssException('RequestCoreException: ' . $e->getMessage())); } $response_header = $request->get_response_header(); $response_header['oss-request-url'] = $requestUrl; $response_header['oss-redirects'] = $this->redirects; $response_header['oss-stringtosign'] = $string_to_sign; $response_header['oss-requestheaders'] = $request->request_headers; $data = new ResponseCore($response_header, $request->get_response_body(), $request->get_response_code()); //retry if OSS Internal Error if ((integer)$request->get_response_code() === 500) { if ($this->redirects <= $this->maxRetries) { //Sets the sleep time betwen each retry. $delay = (integer)(pow(4, $this->redirects) * 100000); usleep($delay); $this->redirects++; $data = $this->auth($options); } } $this->redirects = 0; return $data; }
可以看到拋異常情況只在send_request
方法,而裡面只在curl本身無法請求(比如host無法解析)才會丟擲RequestCore_Exception
異常
也就是說如果是業務類的錯誤是會正常走下去的
雖然response_code
為500時會有重試,但是在這之前已經建立了response
物件
如果非500錯誤,或者超過重試次數都會返回這個物件,最終情況就是不管怎麼樣都會返回result
結構體
解決
在拿到result
結構體後先進行response_code
判斷,程式碼如下
public function oss(string $file, string $object)
{
$ossClient = new OssClient($this->config['accessKeyId'], $this->config['accessKeySecret'], $this->config['endpoint']);
$result = $ossClient->uploadFile($this->config['bucket'], ltrim($object, '/'), $file);
if ($result['info']['http_code'] !== 200) {
throw new OssException('上傳失敗');
}
return $result['oss-request-url'];
}
補充
查閱了官方示例也沒有對這些情況進行處理,示例如下:
地址:https://help.aliyun.com/document_detail/88473.html
// ...省略程式碼
try{
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
$ossClient->uploadFile($bucket, $object, $filePath);
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . "OK" . "\n");
附上文件中其他錯誤碼說明,文件連結:https://help.aliyun.com/document_detail/31978.html#section-orz-dlw-bz
錯誤碼 | HTTP狀態碼 | 描述 |
---|---|---|
MissingContentLength | 411 | 請求頭沒有采用chunked encoding編碼方式,或沒有設定Content-Length引數。 |
InvalidEncryptionAlgorithmError | 400 | 指定x-oss-server-side-encryption的值無效。取值:AES256、KMS或SM4。 |
AccessDenied | 403 | 新增Object時,使用者對設定的Bucket沒有訪問許可權。 |
NoSuchBucket | 404 | 新增Object時,設定的Bucket不存在。 |
InvalidObjectName | 400 | 傳入的Object key長度大於1023位元組。 |
InvalidArgument | 400 | 返回該錯誤的可能原因如下:新增的Object大小超過5 GB。x-oss-storage-class等引數的值無效。 |
RequestTimeout | 400 | 指定了Content-Length,但沒有傳送訊息體,或者傳送的訊息體小於指定的大小。此種情況下伺服器會一直等待,直至請求超時。 |
Bad Request | 400 | 在請求中指定Content-MD5後,OSS會計算所傳送資料的MD5值,並與請求中Conent-MD5的值進行比較。如果二者不一致,則返回該錯誤。 |
KmsServiceNotEnabled | 403 | 將x-oss-server-side-encryption指定為KMS,但沒有預先購買KMS套件。 |
FileAlreadyExists | 409 | 當請求的Header中攜帶x-oss-forbid-overwrite=true 時,表示禁止覆蓋同名檔案。如果同名檔案已存在,則返回該錯誤。 |
FileImmutable | 409 | Bucket中的資料處於被保護狀態時,如果嘗試刪除或修改相應資料,則返回該錯誤。 |