前言
做好了七牛雲存儲,又要換阿里雲oss。。。哎。。。
記錄一下過程。本次采用的是服務端生成簽名。web端直傳的方式。沒設置回調
一、准備工作
瀏覽使用手冊:
幾個關鍵的手冊頁面:
1、服務端簽名后直傳
2、php代碼示例
3、PostObject API 說明
二、原理
1、用戶發送上傳Policy請求到應用服務器。
2、應用服務器返回上傳Policy和簽名給用戶。
3、用戶直接上傳數據到OSS
(我是直接把簽名生成到web頁面)
三、開始開發
下載官方php demo。
打開demo中的get.php,如圖。
可見,就是我們輸入自己oss的一些配置信息,然后返回reponse數組。我理解為reponse這個數組就是返回的簽名。
上面的配置信息都可以寫入數據庫中,然后從數據庫讀取。。
例如:
四、后端代碼:
采用的是thinkphp5框架開發。
從數據庫里面把配置讀出來,然后復制上面demo的代碼,返回reponse數組到前端。
這里是上傳兩個文件。一個到公共bucket,一個到私有bucket。所以。reponse數組會多了幾個參數。
public function oss_addStep(){
function gmt_iso8601($time) {
$dtStr = date("c", $time);
$mydatetime = new \DateTime($dtStr);
$expiration = $mydatetime->format(\DateTime::ISO8601);
$pos = strpos($expiration, '+');
$expiration = substr($expiration, 0, $pos);
return $expiration."Z";
}
$ossData = Db::name('oss_setting')->find();
if(!$ossData){
$this->error('請先配置OSS配置');
}
$id = $ossData['access_key'];
$key = $ossData['secret_key'];
// $id= '<yourAccessKeyId>'; // 請填寫您的AccessKeyId。
// $key= '<yourAccessKeySecret>'; // 請填寫您的AccessKeySecret。
$bucket1 = $ossData['bucket1'];
$bucket2 = $ossData['bucket2'];
$domain1 = $ossData['domain1'];
$domain2 = $ossData['domain2'];
// $host的格式為 bucketname.endpoint,請替換為您的真實信息。
$host1 = 'http://'.$bucket1.'.'.$domain1;
$host2 = 'http://'.$bucket2.'.'.$domain2;
// $callbackUrl為上傳回調服務器的URL,請將下面的IP和Port配置為您自己的真實URL信息。
$dir1 = '';
$dir2 = ''; // 用戶上傳文件時指定的前綴。;
$now = time();
$expire = 100; //設置該policy超時時間是10s. 即這個policy過了這個有效時間,將不能訪問。
$end = $now + $expire;
$expiration = gmt_iso8601($end);
//最大文件大小.用戶可以自己設置
$condition = array(0=>'content-length-range', 1=>0, 2=>1048576000);
$conditions[] = $condition;
// 表示用戶上傳的數據,必須是以$dir開始,不然上傳會失敗,這一步不是必須項,只是為了安全起見,防止用戶通過policy上傳到別人的目錄。
$start = array(0=>'starts-with', 1=>'$key', 2=>$dir1);
$conditions[] = $start;
$arr = array('expiration'=>$expiration,'conditions'=>$conditions);
$policy = json_encode($arr);
$base64_policy = base64_encode($policy);
$string_to_sign = $base64_policy;
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true));
$condition2 = array(0=>'content-length-range', 1=>0, 2=>1048576000);
$conditions2[] = $condition2;
$start2 = array(0=>'starts-with', 1=>'$key', 2=>$dir2);
$conditions2[] = $start2;
$arr2 = array('expiration'=>$expiration,'conditions'=>$conditions2);
$policy2 = json_encode($arr2);
$base64_policy2 = base64_encode($policy2);
$string_to_sign2 = $base64_policy2;
$signature2 = base64_encode(hash_hmac('sha1', $string_to_sign2, $key, true));
$response = array();
$response['accessid'] = $id;
$response['host1'] = $host1;
$response['host2'] = $host2;
$response['policy'] = $base64_policy;
$response['policy2'] = $base64_policy2;
$response['signature'] = $signature;
$response['signature2'] = $signature2;
$response['expire'] = $end;
$response['dir1'] = $dir1; // 這個參數是設置用戶上傳文件時指定的前綴。
$response['dir2'] = $dir2; // 這個參數是設置用戶上傳文件時指定的前綴。
$this->assign('response',$response);
return $this->fetch();
}
五、前端代碼:
必須要設置好bucket的跨域規則。
開post權限
把reponse數組的參數渲染到模板中。
至於為什么這樣寫呢。。請細看阿里雲官方的 API PostObject
<form action=" method="post" class="ajaxForm2" id="form1">
<input type="hidden" name="OSSAccessKeyId" id="accessid" value="{$response.accessid}">
<input type="hidden" name="policy" id="policy" value="{$response.policy}">
<input type="hidden" name="signature" id="signature" value="{$response.signature}">
<input type="hidden" name="expire" id="expire" value="{$response.expire}">
<input type="hidden" name="success_action_status" id="success_action_status" value="200">
<input type="hidden" name="key" id="key1_name" value="">
<input type="file" style="display: none;" name="file" id="file1" value="" class="" >
</form>
<form action="" method="post" class="ajaxForm2" id="form2">
<input type="hidden" name="OSSAccessKeyId" id="accessid" value="{$response.accessid}">
<input type="hidden" name="policy" id="policy" value="{$response.policy2}">
<input type="hidden" name="signature" id="signature" value="{$response.signature2}">
<input type="hidden" name="expire" id="expire" value="{$response.expire}">
<input type="hidden" name="success_action_status" id="success_action_status" value="200">
<input type="hidden" name="key" id="key2_name" value="">
<input type="file" style="display: none;" name="file" id="file2" value="" class="" />
</form>
效果如圖:
ajax 部分:
$.ajax({
url : '{$response.host1}',
type : 'post',
data : new FormData($('#form1')[0]),
dataType:'XML',
processData: false,
contentType: false,
error:function(xml){
console.log(xml.responseText);
layer.msg('上傳失敗');
},
success:function(){
$("#key1").val(key_name);
$("#up_key1").val(key_name);
layer.msg('上傳成功');
}
})