1. 程式人生 > >阿里oss儲存API介面封裝呼叫(PHP)

阿里oss儲存API介面封裝呼叫(PHP)

這篇是php後臺封裝的OSS物件儲存API介面類
<?php
/**
 * OSS 阿里雲平臺上傳刪除介面
 * 使用前請進行一些必須的設定 在bucket屬性裡 設定該讀寫許可權(ACL)為 公共讀 要不然上傳的圖片無法顯示
 * Cors設定 一般是 post方法,自己根據情況而設定,要不然上傳不了圖片或檔案,我設定為 GET POST 來源使用*
 * @author jorsh 20160127
 *
 **/
class Ossupload{
    public $ossconfig = array(
        'id'=>'LTA******X5h',   //Access Key ID
        'key'=>'6dLVH###########bIdxf6nh', //Access Key Secret
        'bucketname'=>'yix####ng', //bucket名稱  刪除時需要填坑
        'host'=>'http://filename.yixiansheng.com', //上傳提交地址 格式:bucketname+區別+阿里的域名 列如:http://d****a-t.img-cn-beijing.aliyuncs.com/
        'expire' => 30, //過期時間
        'callback_body' => array(
            'callbackUrl'=>'', //回撥地址全地址含有引數
            'callbackHost'=>'', //回撥域名
            'callbackBody'=>'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', //阿里返回的圖片資訊
            'callbackBodyType'=>'application/x-www-form-urlencoded', //設定阿里返回的資料格式
        ),
        'maxfilesize'=>10485760, //限制上傳檔案大小 這裡是10M
        'imghost' =>'http://d****a-t.img-cn-beijing.aliyuncs.com/', //前臺顯示圖片的地址 格式不多說
    );

    public function _initialize() {
        $this->ossconfig['callback_body']['callbackUrl']='http://'.$_SERVER['HTTP_HOST'].'/s****n.php/ossupload/cupload/'; //初始化回撥地址
        $this->ossconfig['callback_body']['callbackHost']=$_SERVER['HTTP_HOST']; //初始化回撥域名
    }

    //獲取policy和回撥地址 一般使用jajx或是在載入頁面的時候會用到policy和回撥地址,還有傳限制大小等
    public function getpolicy(){
        //過期時間 不得不說那個T和Z這個得注意(阿里demo的那個函式不知道就是使用不了,我這樣是可以使用的)
        $expire = $this->ossconfig['expire']+time();
        $expire = date('Y-m-d').'T'.date('H:i:s').'Z';
        //$expiration = $this->gmt_iso8601($expire);
        //獲取上傳的路徑
        $dir = $this->uploadpath(I('path')); //這裡要獲得上傳的路徑有一個引數path 具體看uploadpath這個方法,根據專案自己設定

        //這個就是policy
        $policy = array(
            'expiration' =>$expire, //過期時間
            'conditions' =>array(
                0=>array(0=>'content-length-range', 1=>0, 2=>$this->ossconfig['maxfilesize']), //限制上傳檔案的大小
                1=>array(0=>'starts-with', 1=>'$key', 2=>$dir), //這裡的'$key' 一定要注意
            ),
        );
        //上面的'$key' 自定義使用哪個引數來做上傳檔案的名稱.
        //而這個'$key'並不是一個值,只是告訴OSS伺服器使用哪個引數來作為上傳檔案的名稱
        //注意是全路徑,比如前端上傳圖片的使用提交的地址中&key=upload/images/20160127${filename}
        //那麼在上傳圖片的時候就要拼接出key的路徑然後和圖片一起提交給oss伺服器
        //你上傳的圖片的名子是5566.png ,那麼儲存在oss的圖片路徑 就是upload/images/201601275566.png;
        //而後面的$dir 就是upload/images/
        $policy = base64_encode(json_encode($policy));
        $signature = base64_encode(hash_hmac('sha1', $policy, $this->ossconfig['key'], true)); //簽名演算法

        $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)), //我這裡使用時間和隨時資料作為上傳檔案的名子
            'maximgfilesize'=>307200, //前端JS判斷 可以上傳的圖片的大小 這裡是300K
        );
        $this->ajaxReturn(array('status'=>0, 'msg'=>'', 'config'=>$res),'json');
    }

    //回撥處理方法 這裡使用OSS demo裡的東西,但demo裡有個坑就是一定要告訴其內容長度 content-lenght的值具體看 _msg()方法
    //這裡面還有一些設定可以檢視OSS介面說明的地方,我這裡沒有設定,可以獲到頭部的資訊
    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的簽名
        $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);
        curl_close($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){
            //增加對上圖片的型別的判斷
            if(!in_array(I('mimeType'), array('image/png', 'image/gif', 'image/jpeg'))){
                $this->_msg(array("Status"=>"error",'msg'=>'不支援的檔案型別'));
            }
            //if(I('size')>$this->ossconfig['maxfilesize']){
            if(I('size')>512000){
                $this->_msg(array("Status"=>"error",'msg'=>'上傳圖片過大,無法上傳'));
            }
            $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'=>'上傳失敗,請重新上傳'));
        }
    }
    //返回要上傳的路徑 注意這裡的路徑 最前最不要有/符號,否則會出錯
    public function uploadpath($type){
        switch ($type) {
            case '1':
                $patch = 'Upload/images/';
                break;

            default:
                # code...
                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);
    }

    //刪除圖片或檔案資訊 這裡有個坑就簽名演算法這塊
    //這個刪除是單一檔案刪除,估計批量刪除可以就沒有問題了
    //單一圖片刪除使用delete 所以傳遞的內容為空,就不要使用md5加密
    //然後刪除成功了,OSS服務不返回任務內容 坑
    //還有就是地址這塊在算簽名的時候一定要加個bucketname這點最坑
    public function delosspic($picurl){
        if(empty($picurl)){
            return array('status'=>1, 'msg'=>'要刪除的圖片不能為空');
        }
        if(strpos($picurl, $this->ossconfig['host'])===false){
            $picurl = trim($picurl,'/');
            $url = $this->ossconfig['host'].'/'.$picurl;
            $picurl = '/'.$this->ossconfig['bucketname'].'/'.$picurl; //一定要加上 bucketname 坑啊,官方沒有說明
        }else{
            $url = $picurl;
            $picurl = str_replace($this->ossconfig['host'], '', $picurl);
            $picurl = trim($picurl, '/');
            $picurl = '/'.$this->ossconfig['bucketname'].'/'.$picurl;
        }
        $gtime = gmdate("D, d M Y H:i:s").' GMT'; //一定要使用 http 1.1 標準時間格式
        //簽名演算法不多說官網的例子也只能無語,沒有PHP版的。本人這個可以使用驗證通過,可以正常刪除檔案
        $signature = base64_encode(hash_hmac('sha1',"DELETE\n\ntext/html\n".$gtime."\n".$picurl, $this->ossconfig['key'], true));
        //傳遞頭這裡也是坑 上面使用了 text/html靠,在協議頭裡還得加上,要不然會提示出錯。
        $headers = array(
            'Authorization: OSS '.$this->ossconfig['id'].':'.$signature,
            'Date:'.$gtime, //靠時間也得帶上
            'Content-Type: text/html', //傳遞型別要與上面簽名演算法一直
        );
        $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);
        $ret = curl_exec($ch);

        curl_close($ch);
        return $ret;
        //靠,OSS刪除檔案不返回結果,沒有返回結果就表示刪除成功,反之會有刪除出錯資訊
    }


}

 下一篇是前端直傳OSS