一、爲什(shén)麽要用(yòng)oss
将網站的(de)靜态資源存儲在oss上,靜态資源包括網站圖片,html,js,css文件,通(tōng)過cdn将靜态資源分(fēn)布式緩存在各個(gè)節點上實現就就近訪問,提高(gāo)用(yòng)戶訪問的(de)響應速度.
二、oss怎麽用(yòng)
1.在阿裏雲産品與服務找到-對(duì)象存儲oss
2.創建Bucket設置該讀寫權限(ACL)爲 公共讀
3.在AccessKey 管理(lǐ)創建AccessKey
三、創建上傳控制器
class AliossController extends FwadminController {
private $oss_host = 'https://youboxunguanwang.oss-cn-shenzhen.aliyuncs.com';//'https://yifajian2020.oss-cn-beijing.aliyuncs.com';//阿裏雲oss 外網地址endpoint
private $oss_key_id = '';//阿裏雲oss Access Key ID
private $oss_key_secret = '';//阿裏雲oss Access Key Secret
private $oss_bucket_name = '';//創建的(de)bucket名稱
private $oss_endpoint = 'oss-cn-shenzhen.aliyuncs.com';//阿裏雲OSS外網地址
/*
* 獲得(de)簽名
* @param string $path 保存路徑
* @return json
*/
public function get_sign($path = '') {
$now = time();
$expire = 300000; //設置該policy超時(shí)時(shí)間是30s. 即這(zhè)個(gè)policy過了(le)這(zhè)個(gè)有效時(shí)間,将不能訪問
$end = $now + $expire;
$expiration = $this->gmt_iso8601($end);
//最大(dà)文件大(dà)小.用(yòng)戶可(kě)以自己設置
$condition = array(0=>'content-length-range', 1=>0, 2=>10485760000);
$conditions[] = $condition;
//表示用(yòng)戶上傳的(de)數據,必須是以$dir開始, 不然上傳會失敗,這(zhè)一步不是必須項,隻是爲了(le)安全起見,防止用(yòng)戶通(tōng)過policy上傳到别人(rén)的(de)目錄
$start = array(0=>'starts-with', 1=>$this->oss_key_secret, 2=>$path);
$conditions[] = $start;
$arr = array('expiration'=>$expiration,'conditions'=>$conditions);
//echo json_encode($arr);
//return;
$policy = json_encode($arr);
$base64_policy = base64_encode($policy);
$string_to_sign = $base64_policy;
$signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->oss_key_secret, true));
$response = array();
$response['accessid'] = $this->oss_key_id;
$response['host'] = $this->oss_host;
$response['policy'] = $base64_policy;
$response['signature'] = $signature;
$response['expire'] = $end;
//這(zhè)個(gè)參數是設置用(yòng)戶上傳指定的(de)前綴
$response['dir'] = $path;
echo json_encode($response);
return ;
}
function gmt_iso8601($time) {
$dtStr = date("c", $time);
$mydatetime = new \DateTime($dtStr);
$expiration = $mydatetime->format(\DateTime::ISO8601);
$pos = strpos($expiration, '+');
$expiration2 = substr($expiration, 0, $pos);
return $expiration2."Z";
}
}
上傳文件
/**
* 上傳文件操作
*/
class AliossdController extends FwadminController {
/*
public $ossconfig = array(
public $ossconfig = array(
'id'=>'',//Access Key ID
'key'=>'', //Access Key Secret
'bucketname'=>'xxxx', //bucket名稱
'host'=>'https://xxxx.oss-cn-beijing.aliyuncs.com', //上傳提交地址 格式:bucketname+區(qū)别+阿裏的(de)域名
'expire' => 30, //過期時(shí)間
'callback_body' => array(
'callbackUrl'=>'', //回調地址全地址含有參數
'callbackHost'=>'', //回調域名
'callbackBody'=>'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', //阿裏返回的(de)圖片信息
'callbackBodyType'=>'application/x-www-form-urlencoded', //設置阿裏返回的(de)數據格式
),
'maxfilesize'=>10485760, //限制上傳文件大(dà)小 這(zhè)裏是10M
'imghost' =>'https://xxxx.oss-cn-beijing.aliyuncs.com', //前台顯示圖片的(de)地址 格式不多(duō)說
);
public function _initialize() {
$this->ossconfig['host']= 'https://'.$this->ossconfig['bucketname'].'.oss-cn-beijing.aliyuncs.com'; //初始化(huà)上傳地址
$this->ossconfig['callback_body']['callbackUrl']='https://'.$_SERVER['HTTP_HOST'].'/s****n.php/ossupload/cupload/'; //初始化(huà)回調地址
$this->ossconfig['callback_body']['callbackHost']=$_SERVER['HTTP_HOST']; //初始化(huà)回調域名
}
//獲取policy和(hé)回調地址 一般使用(yòng)jajx或是在加載頁面的(de)時(shí)候會用(yòng)到policy和(hé)回調地址,還(hái)有傳限制大(dà)小等
public function getpolicy(){
//過期時(shí)間 不得(de)不說那個(gè)T和(hé)Z這(zhè)個(gè)得(de)注意(阿裏demo的(de)那個(gè)函數不知道就是使用(yòng)不了(le),我這(zhè)樣是可(kě)以使用(yòng)的(de))
$expire = $this->ossconfig['expire']+time();
$expire = date('Y-m-d').'T'.date('H:i:s').'Z';
//$expiration = $this->gmt_iso8601($expire);
//獲取上傳的(de)路徑
$dir = $this->uploadpath(I('path')); //這(zhè)裏要獲得(de)上傳的(de)路徑有一個(gè)參數path 具體看uploadpath這(zhè)個(gè)方法,根據項目自己設置
//這(zhè)個(gè)就是policy
$policy = array(
'expiration' =>$expire, //過期時(shí)間
'conditions' =>array(
0=>array(0=>'content-length-range', 1=>0, 2=>$this->ossconfig['maxfilesize']), //限制上傳文件的(de)大(dà)小
1=>array(0=>'starts-with', 1=>'$key', 2=>$dir), //這(zhè)裏的(de)'$key' 一定要注意
),
);
//上面的(de)'$key' 自定義使用(yòng)哪個(gè)參數來(lái)做(zuò)上傳文件的(de)名稱.
//而這(zhè)個(gè)'$key'并不是一個(gè)值,隻是告訴OSS服務器使用(yòng)哪個(gè)參數來(lái)作爲上傳文件的(de)名稱
//注意是全路徑,比如前端上傳圖片的(de)使用(yòng)提交的(de)地址中&key=upload/images/20160127${filename}
//那麽在上傳圖片的(de)時(shí)候就要拼接出key的(de)路徑然後和(hé)圖片一起提交給oss服務器
//你上傳的(de)圖片的(de)名子是5566.png ,那麽保存在oss的(de)圖片路徑 就是upload/images/201601275566.png;
//而後面的(de)$dir 就是upload/images/
$policy = base64_encode(json_encode($policy));
$signature = base64_encode(hash_hmac('sha1', $policy, $this->ossconfig['key'], true)); //簽名算(suàn)法
$res = array(
'accessid'=>$this->ossconfig['id'],
'host' =>$this->ossconfig['host'],
'policy' => $policy,
'signature'=>$signature,
'expire' =>$expire,
'callback' =>base64_encode(json_encode($this->ossconfig['callback_body'])),
'dir' =>$dir,
'filename' =>md5(date('YmdHis').rand(1000,9999)), //我這(zhè)裏使用(yòng)時(shí)間和(hé)随時(shí)數據作爲上傳文件的(de)名子
'maximgfilesize'=>307200, //前端JS判斷 可(kě)以上傳的(de)圖片的(de)大(dà)小 這(zhè)裏是300K
);
$this->ajaxReturn(array('status'=>0, 'msg'=>'', 'config'=>$res),'json');
}
//回調處理(lǐ)方法 這(zhè)裏使用(yòng)OSS demo裏的(de)東西,但demo裏有個(gè)坑就是一定要告訴其内容長(cháng)度 content-lenght的(de)值具體看 _msg()方法
//這(zhè)裏面還(hái)有一些設置可(kě)以查看OSS接口說明(míng)的(de)地方,我這(zhè)裏沒有設置,可(kě)以獲到頭部的(de)信息
public function cupload(){
$authorizationBase64 = '';
$pubKeyUrlBase64 = '';
if(isset($_SERVER['HTTP_AUTHORIZATION'])){
$authorizationBase64 = $_SERVER['HTTP_AUTHORIZATION'];
}
if (isset($_SERVER['HTTP_X_OSS_PUB_KEY_URL'])){
$pubKeyUrlBase64 = $_SERVER['HTTP_X_OSS_PUB_KEY_URL'];
}
if ($authorizationBase64 == '' || $pubKeyUrlBase64 == ''){
//header("http/1.1 403 Forbidden");
$this->_msg(array("Status"=>"error",'msg'=>'上傳失敗,請重新上傳'));
}
//獲取OSS的(de)簽名
$authorization = base64_decode($authorizationBase64);
//獲取公鑰
$pubKeyUrl = base64_decode($pubKeyUrlBase64);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $pubKeyUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$pubKey = curl_exec($ch);
if ($pubKey == ""){
//header("http/1.1 403 Forbidden");
$this->_msg(array("Status"=>"error",'msg'=>'上傳失敗,請重新上傳'));
}
//獲取回調body
$body = file_get_contents('php://input');
//拼接待簽名字符串
$authStr = '';
$path = $_SERVER['REQUEST_URI'];
$pos = strpos($path, '?');
if ($pos === false){
$authStr = urldecode($path)."\n".$body;
}else{
$authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body;
}
//驗證簽名
$ok = openssl_verify($authStr, $authorization, $pubKey, OPENSSL_ALGO_MD5);
if ($ok == 1){
//增加對(duì)上圖片的(de)類型的(de)判斷
if(!in_array(I('mimeType'), array('image/png', 'image/gif', 'image/jpeg'))){
$this->_msg(array("Status"=>"error",'msg'=>'不支持的(de)文件類型'));
}
//if(I('size')>$this->ossconfig['maxfilesize']){
if(I('size')>512000){
$this->_msg(array("Status"=>"error",'msg'=>'上傳圖片過大(dà),無法上傳'));
}
$this->_msg(array("Status"=>"Ok",'msg'=>'','pic'=>$this->ossconfig['imghost'].I('filename')));
}else{
//header("http/1.1 403 Forbidden");
$this->_msg(array("Status"=>"error",'msg'=>'上傳失敗,請重新上傳'));
}
}
//返回要上傳的(de)路徑 注意這(zhè)裏的(de)路徑 最前最不要有/符号,否則會出錯
public function uploadpath($type){
switch ($type) {
case '1':
$patch = 'Upload/images/';
break;
}
return $patch;
}
public 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";
}
public function _msg($arr){
$data = json_encode($arr);
header("Content-Type: application/json");
header("Content-Length: ".strlen($data));
exit($data);
}
//删除圖片或文件信息 這(zhè)裏有個(gè)坑就簽名算(suàn)法這(zhè)塊
//這(zhè)個(gè)删除是單一文件删除,估計批量删除可(kě)以就沒有問題了(le)
//單一圖片删除使用(yòng)delete 所以傳遞的(de)内容爲空,就不要使用(yòng)md5加密
//然後删除成功了(le),OSS服務不返回任務内容 坑
//還(hái)有就是地址這(zhè)塊在算(suàn)簽名的(de)時(shí)候一定要加個(gè)bucketname這(zhè)點最坑
public function delosspic($picurl){
if(empty($picurl)){
return array('status'=>1, 'msg'=>'要删除的(de)圖片不能爲空');
}
if(strpos($picurl, $this->ossconfig['host'])===false)
{
$picurl = trim($picurl,'/');
$url = $this->ossconfig['host'].'/'.$picurl;
$picurl = '/'.$this->ossconfig['bucketname'].'/'.$picurl;
}
else{
$url = $picurl;
$picurl = str_replace($this->ossconfig['host'], '', $picurl);
$picurl = trim($picurl, '/');
$picurl = '/'.$this->ossconfig['bucketname'].'/'.$picurl;
}
$url = str_replace('https', 'http', $url);
$gtime = gmdate("D, d M Y H:i:s").' GMT'; //一定要使用(yòng) http 1.1 标準時(shí)間格式
//簽名算(suàn)法不多(duō)說官網的(de)例子也(yě)隻能無語,沒有PHP版的(de)。本人(rén)這(zhè)個(gè)可(kě)以使用(yòng)驗證通(tōng)過,可(kě)以正常删除文件
$signature = base64_encode(hash_hmac('sha1',"DELETE\n\ntext/html\n".$gtime."\n".$picurl, $this->ossconfig['key'], true));
//傳遞頭這(zhè)裏也(yě)是坑 上面使用(yòng)了(le) text/html靠,在協議(yì)頭裏還(hái)得(de)加上,要不然會提示出錯。
$headers = array(
'Authorization: OSS '.$this->ossconfig['id'].':'.$signature,
'Date:'.$gtime, //靠時(shí)間也(yě)得(de)帶上
'Content-Type: text/html', //傳遞類型要與上面簽名算(suàn)法一緻
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
//curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_exec($ch);
//靠,OSS删除文件不返回結果,沒有返回結果就表示删除成功,反之會有删除出錯信息
}
//測試删除一個(gè)圖片文件
public function del_file(){
$url = I('url');
$this->delosspic($url);
echo '1';
}
}
四、其他(tā)js 前端文件
https://pan.baidu.com/s/1P6nZ5iL_AR2U3nZpmfQ5AQ
提取碼:ege2