概述
前幾篇文章:Yii2接入AWS S3管理附件(基礎使用),Yii2接入AWS S3管理附件(分片上傳),Yii2接入AWS S3管理附件(私有附件),我們已經講解了如何上傳附件,和管理私有附件。
這篇文章我們繼續擴展如何處理超大附件。面對超大附件,比如1G的附件,即使使用分片上傳,也需要等好長時間。因爲你的附件需要先上傳到你的服務器,再從你的服務器上傳到s3。所以需要等待很長時間是肯定的了。想到這個原因,解決辦法也就有了,那我們能不能直接將附件上傳到s3,不經過服務器不就快多了嘛。
使用預簽名URL直接上傳附件到s3
s3的預簽名URL不但可以讓我訪問私有附件,也能讓我們直接上傳附件到s3。我們需要做的就是在s3Attachment組件中再增加GetPutPreSignature()方法就能獲得可以put到s3的預簽名URL。
/*
* 獲取附件的PUT預簽名地址
*
* @param string $key 附件公網訪問地址.
* @param string $content_type 附件類型.
*/
public function GetPutPreSignature($key, $content_type, $expires = '2')
{
if (empty($key) || empty($content_type) || !is_numeric($expires)) {
return false;
}
try {
$config = [
'region' => Yii::$app->params['S3']['region'],
'version' => Yii::$app->params['S3']['version'],
'credentials' => [
'key' => Yii::$app->params['S3']['access_key_id'],
'secret' => Yii::$app->params['S3']['access_key_secret'],
],
];
$sdk = new Sdk($config);
$client = $sdk->createS3();
$cmd = $client->getCommand('PutObject', [
'Bucket' => Yii::$app->params['S3Bucket'],
'Key' => $key,
'ContentType' => $content_type,
'Body' => ''
]);
$request = $client->createPresignedRequest($cmd, '+' . $expires . ' hours');
$pre_signature_url = (string) $request->getUri();
} catch (AwsException $e) {
Yii::info('獲取附件的PUT預簽名地址,錯誤信息:' . $e->getMessage(), 'exception');
return false;
}
return $pre_signature_url;
}
跟GetPreSignature()方法一樣,GetPutPreSignature()方法也需要指定一個過期時間,可以根據業務需要自行修改。
使用ajax通過預簽名URL上傳附件
我們已經通過GetPutPreSignature()拿到了預簽名URL,現在只需要通過ajax向該URL發起put請求就行了。
jQuery("document").ready(function($){
$('.submit').click(function(e){
e.preventDefault();
$.ajax({
url: url,
method: 'PUT',
headers: {
'Content-Type': file.type
},
processData: false,
data: file,
success: function () {
$('#form').submit();
},
error: function (error) {
console.log(error);
}
});
});
});
以上上示例代碼需要根據自身的需求修改一下。整體的想法就是點擊提交的時候,阻止表單提交,先使用ajax向我們拿到的預簽名URL發起PUT請求,將file上傳到s3。之後再提交表單。
至此Yii2通過接入AWS S3管理附件相關的功能都講解完了。如果你也遇到同樣的需求、問題,希望可以幫到你。