php阿里雲oss文件上傳


php的文件上傳

文件上傳

php的文件上傳放在了$_FILES數組里,單文件和多文件上傳的區別在於$_FILES['userfile']['name']是否為數組,
不熟悉的可以讀一下官方文檔 單文件上傳 多文件上傳

阿里雲oss web直傳實踐

這里采用的是服務端簽名后上傳,沒有使用回調。

阿里雲提供了一個php和前端的示例,不過有點坑人,前端采用的是plupload插件,這種demo應該使用原生js更合適啊,畢竟上傳的js插件各不相同。
使用jquery的ajax上傳時,始終上傳失敗,於是用fiddler抓包demo,才知道了上傳給oss的詳細參數格式。

吐槽完畢,下面才是正式上菜。

  • 服務端生成policy,這里使用php
    下面的代碼是從官方demo修改而來,可以通過Facade模式增加靜態方法,方便調用。
    注意dir目錄不能使用"/"開始。下面的簽名算法來自阿里雲的demo。
<?php
class OssPolicy
{

    private $oss_bucket ;
    private $oss_host;
    private $oss_appid;
    private $oss_appsecret;
    private $oss_expire ;//過期時間
    /**
     * OssPolicy constructor.
     * @param $bucket 阿里雲oss的bucket
     * @param $host 對應bucket的host
     * @param $appId app_id
     * @param $appSecret app_secret
     * @param int $expire 過期時間
     */
    public function __construct($bucket,$host,$appId,$appSecret,$expire=900) {
        $this->oss_expire = $expire;
        $this->oss_bucket = $bucket;
        $this->oss_host = $host;
        $this->oss_appid = $appId;
        $this->oss_appsecret = $appSecret;
    }

    private function gmt_iso8601($time) {
        $dtStr = date("c", $time); //格式為2016-12-27T09:10:11+08:00
        $mydatetime = new DateTime($dtStr);
        $expiration = $mydatetime->format(DateTime::ISO8601); //格式為2016-12-27T09:12:32+0800
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);//格式為2016-12-27T09:12:32
        return $expiration."Z";
    }

    /**
     * @function getPolicy 獲取policy
     * @author 
     * @version 1.0
     * @date
     * @param $dir 上傳目錄
     * @param $maxSize 最大文件大小 單位M
     * @param int $expireTime 過期時間
     * @return $array policy
     */
    public function getPolicy($dir,$maxSize=100,$expireTime=null){
        $expireTime = isset($expireTime) ? $expireTime : $this->oss_expire;
        $end = time() + $expireTime;
        $expiration = $this->gmt_iso8601($end);

        $conditions = [];
        $conditions[] = array(0=>'content-length-range', 1=>0, 2=>1024*1024*$maxSize); // 最大文件大小.用戶可以自己設置 100M

        $start = array(0=>'starts-with', 1=>'$key', 2=>$dir); //表示用戶上傳的數據,必須是以$dir開始, 不然上傳會失敗,這一步不是必須項,只是為了安全起見,防止用戶通過policy上傳到別人的目錄
        $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, $this->oss_appsecret, true));

        $response = array();
        $response['accessid'] = $this->oss_appid;
        $response['host'] = $this->oss_host;
        $response['policy'] = $base64_policy;
        $response['signature'] = $signature;
        $response['expire'] = $end;
        $response['bucket'] = $this->oss_bucket;
        $response['dir'] = $dir;  //這個參數是設置用戶上傳指定的前綴

        return $response;
    }
}
  • 前端
    過程 想后端請求policy,上傳到阿里雲,成功后通知后端
    不要問我代碼為啥這么亂,我不生產代碼,我只是代碼的搬運工(從阿里雲demo里搬出來,稍加修改)
    在用表單提交時,注冊一下提交處理的函數,取出文件,然后OssUpload()即可。
oss_accessid = ''
oss_accessoss_key = ''
oss_host = ''
oss_policyBase64 = ''
oss_signature = ''
oss_callbackbody = ''
oss_filename = ''
oss_key = ''
oss_expire = 0
g_object_name = ''
g_object_name_type = 'local_name'
OSS_FILE_NAME_TYPE_LOCAL = "local_name"
OSS_FILE_NAME_TYPE_RANDOM = "random_name"

oss_now = oss_timestamp = Date.parse(new Date()) / 1000;

//向服務端請求policy
function send_request() {
    
}
//生成簽名
function get_oss_signature() {
    //可以判斷當前oss_expire是否超過了當前時間,如果超過了當前時間,就重新取一下.3s 做為緩沖
    oss_now = oss_timestamp = Date.parse(new Date()) / 1000;
    if (oss_expire < oss_now + 3) {
        body = send_request()
        var obj = eval("(" + body + ")");
        oss_host = obj['host']
        oss_policyBase64 = obj['policy']
        oss_accessid = obj['accessid']
        oss_signature = obj['signature']
        oss_expire = parseInt(obj['expire'])
        oss_callbackbody = obj['callback']
        oss_key = obj['dir']

    }

}

//隨機字符串
function random_string(len) {
    len = len || 32;
    var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    var maxPos = chars.length;
    var str = '';
    for (i = 0; i < len; i++) {
        str += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return str;
}
//獲取文件名后綴
function get_suffix(filename) {
    pos = filename.lastIndexOf('.')
    suffix = ''
    if (pos != -1) {
        suffix = filename.substring(pos)
    }
    return suffix;
}
//根據文件名類型 臨時文件還是原始文件名,返回文件名
function calculate_object_name(filename) {
    if (g_object_name_type == 'local_name') {
        g_object_name = oss_key + "${filename}"
    }
    else if (g_object_name_type == 'random_name') {
        suffix = get_suffix(filename)
        g_object_name = oss_key + random_string(10) + suffix
    }
    return ''
}

//把policy填充到Formdata里
function set_upload_param(file) {

    get_oss_signature()
    if (file) {

        calculate_object_name(file.name);
        var res = {
            'key': g_object_name,
            'policy': oss_policyBase64,
            'OSSAccessKeyId': oss_accessid,
            'success_action_status': '200', //讓服務端返回200,不然,默認會返回204
//                'callback': oss_callbackbody,
            'signature': oss_signature,
        };

        var form_data = new FormData();
        for ( var key in res ) {
            form_data.append(key, res[key]);
        }
        form_data.append("file",file);

        return res;
    }

    return false;

}

//上傳到阿里雲 callBack 是用來在上傳成功后通知服務端
function OssUpload( file,fileNameType,callBack) {
    g_object_name_type = fileNameType;
    var form_data = set_upload_param(file.name);
    
    if(!form_data){
        alert("form_data error")
        return
    }
    var fileFullName = oss_host+form_data.get("key");
   
    $.ajax({
        url: oss_host,
        data: form_data,
        processData: false,
        cache: false,
        async: false,
        type:'POST',
        contentType: false,//這個就是了
        success: function (data, textStatus, request) {
           
            //textStatus === "success" 表示成功
            if(typeof callBack === "function") {
                callBack(fileFullName,form_data.get("policy"),textStatus);
            }

        },
        error : function(responseStr) {
          
            if(typeof callBack === "function") {
                callBack(fileFullName,form_data.get("policy"),responseStr.responseText);
            }
        }
    });
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM