• 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);
                }
            }
        });
    }
    
  • 相关阅读:
    java抽象类
    java不支持多继承
    logback颜色
    @ConfigurationProperties、@Value、@PropertySource
    redis命令
    mac下安装rabbitmq
    mac下安装jmeter
    python TypeError: 'int' object is not callable 问题解决
    白炽灯串联发光问题_高中知识(原创)
    python 离散序列 样本数伸缩(原创)
  • 原文地址:https://www.cnblogs.com/xdao/p/php_ossupload.html
Copyright © 2020-2023  润新知