TP6 阿里云OSS(请求服务端签名,客户端直传)

插件合集

点击跳转

下载地址

http://gosspublic.alicdn.com/doc/oss-h5-upload-js-direct.zip?spm=a2c4g.11186623.2.11.4a383bd3mBCqlZ&file=oss-h5-upload-js-direct.zip

点击下载

基类

<?php
/**
 * Created by PhpStorm.
 * User: 张永峰
 * Date: 2021/3/2
 * Time: 9:55
 * ━━━━━━━━━神兽出没━━━━━━━━━
 *        ┏┓   ┏┓+ +
 *       ┏┛┻━━━┛┻┓ + +
 *       ┃       ┃  
 *       ┃   ━   ┃ ++ + + +
 *       ████━████ ┃+
 *       ┃       ┃ +
 *       ┃   ┻   ┃
 *       ┃       ┃ + +
 *       ┗━┓   ┏━┛
 *         ┃   ┃           
 *         ┃   ┃ + + + +
 *         ┃   ┃    Code is far away from bug with the animal protecting       
 *         ┃   ┃ +     神兽保佑,代码无bug  
 *         ┃   ┃
 *         ┃   ┃  +         
 *         ┃    ┗━━━┓ + +
 *         ┃        ┣┓
 *         ┃        ┏┛
 *         ┗┓┓┏━┳┓┏┛ + + + +
 *          ┃┫┫ ┃┫┫
 *          ┗┻┛ ┗┻┛+ + + +
 * ━━━━━━━━━感觉萌萌哒━━━━━━━━━
 */


namespace zyf;

/**
 * @title   阿里云OSS存储签名
 * Class Osss
 * @package zyf
 * @Date    : 2021/3/2
 * @Time    : 9:55
 */
class Osss
{
    public function gmt_iso8601($time)
    {
        $expiration = date(DATE_ISO8601, $time);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }

    public function signedUrl()
    {
        $key = config('oss.main.AccessKeySecret');
        $callbackUrl = config('oss.main.callbackUrl');
        $dir = config('oss.main.dir');

        $callback_param = array(
            'callbackUrl' => $callbackUrl,
            'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}',
            'callbackBodyType' => "application/x-www-form-urlencoded");
        $callback_string = json_encode($callback_param);

        $base64_callback_body = base64_encode($callback_string);
        $now = time();
        $expire = 3000;  // 设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问。
        $end = $now + $expire;
        $expiration = $this->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 => $dir);
        $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));

        $response = array();
        $response['accessid'] = config('oss.main.AccessKeyId');
        $response['host'] = config('oss.main.host');
        $response['policy'] = $base64_policy;
        $response['signature'] = $signature;
        $response['expire'] = $end;
        $response['callback'] = $base64_callback_body;
        $response['dir'] = $dir;  // 这个参数是设置用户上传文件时指定的前缀。
        return $response;
    }

}

后台

    // OSS
    public function oss()
    {
        if (IS_POST) {
            $oss = new \zyf\Osss();
            return json($oss->signedUrl());
        }
        return $this->render();
    }

前端

<link rel="stylesheet" href="__COMMON__/oss/style.css">

    <div class="layui-form-item">
        <label class="layui-form-label">上传文件:</label>
        <div class="layui-input-block">
            <h4>您所选择的文件列表:</h4>
            <div id="ossfile">你的浏览器不支持flash,Silverlight或者HTML5!</div>
            <br/>
            <div id="container">
                <a id="selectfiles" href="javascript:void(0);" class='btn'>选择文件</a>
                <a id="postfiles" href="javascript:void(0);" class='btn'>开始上传</a>
            </div>

            <pre id="console"></pre>
            <p>&nbsp;</p>
        </div>
    </div>

    <script type="text/javascript" src="__COMMON__/oss/lib/plupload-2.1.2/js/plupload.full.min.js"></script>
    <script type="text/javascript" src="__COMMON__/oss/upload.js"></script>

JS

把下载的包中的uoload.js修改

修改send_request中的serverUrl

修改new plupload.Uploader中引入静态资源的路径

accessid = ''
accesskey = ''
host = ''
policyBase64 = ''
signature = ''
callbackbody = ''
filename = ''
key = ''
expire = 0

g_object_name = ''
g_object_name_type = ''
now = timestamp = Date.parse(new Date()) / 1000;

function send_request() {
    var xmlhttp = null;
    if (window.XMLHttpRequest) {
        xmlhttp=new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
    if (xmlhttp!=null) {
        // serverUrl是 用户获取 '签名和Policy' 等信息的应用服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
        // serverUrl = '666.com/common/Osss/signedUrl'
        // serverUrl = './php/get.php'
        xmlhttp.open("POST", '', false)
        xmlhttp.send(null)
        return xmlhttp.responseText
    } else {
        alert("Your browser does not support XMLHTTP.");
    }
}

// 生成随机文件名
function check_object_radio() {
    g_object_name_type = 'random_name';
}

// 获取签名
function get_signature()
{
    // 可以判断当前expire是否超过了当前时间, 如果超过了当前时间, 就重新取一下,3s 作为缓冲。
    now = timestamp = Date.parse(new Date()) / 1000;
    if (expire < now + 3) {
        body = send_request()
        var obj = eval("(" + body + ")")
        host = obj['host']
        policyBase64 = obj['policy']
        accessid = obj['accessid']
        signature = obj['signature']
        expire = parseInt(obj['expire'])
        callbackbody = obj['callback']
        key = obj['dir']
        return true;
    }
    return false;
}

// 随机字符串
function random_string(len) {
    len = len || 32;
    var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    var maxPos = chars.length;
    var pwd = '';
    for (i = 0; i < len; i++) {
        pwd += chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

// 获取文件后缀名
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 += "${filename}"
    } else if (g_object_name_type == 'random_name') {
        suffix = get_suffix(filename)
        g_object_name = key + random_string(10) + suffix
    }
    return ''
}

// 获取上传对象名称
function get_uploaded_object_name(filename) {
    if (g_object_name_type == 'local_name') {
        tmp_name = g_object_name
        tmp_name = tmp_name.replace("${filename}", filename);
        return tmp_name
    } else if (g_object_name_type == 'random_name') {
        return g_object_name
    }
}

// 设置上传参数
function set_upload_param(up, filename, ret) {
    if (ret == false) {
        ret = get_signature()
    }
    g_object_name = key;
    if (filename != '') {
        suffix = get_suffix(filename)
        calculate_object_name(filename)
    }
    new_multipart_params = {
        'key' : g_object_name,
        'policy': policyBase64,
        'OSSAccessKeyId': accessid,
        'success_action_status' : '200', //让服务端返回200,不然,默认会返回204
        'callback' : callbackbody,
        'signature': signature,
    };

    up.setOption({
        'url': host,
        'multipart_params': new_multipart_params
    });

    up.start();
}

var uploader = new plupload.Uploader({
    runtimes: 'html5,flash,silverlight,html4',
    browse_button: 'selectfiles',
    container: document.getElementById('container'),
    flash_swf_url: '/static/common/oss/lib/plupload-2.1.2/js/Moxie.swf',
    silverlight_xap_url: '/static/common/oss/ossupload/lib/plupload-2.1.2/js/Moxie.xap',
    url: 'http://oss.aliyuncs.com',
    autostart: true,
    multi_selection: false, //是否支持多文件选择
    init: {
        PostInit: function () {
            document.getElementById('postfiles').onclick = function () {
                set_upload_param(uploader, '', false);
                return false;
            };
        },

        FilesAdded: function (up, files) {
            plupload.each(files, function (file) {
                //   文件信息
                document.getElementById('ossfile').innerHTML = '<input type="hidden" name="filename" value="' + file.name + '"><input type="hidden" name="filesize" value="' + plupload.formatSize(file.size) + '"><div class="onlyfile" data-id="' + file.id + '" id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>'
                    + '<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
                    + '</div>';
            });
        },

        BeforeUpload: function (up, file) {
            check_object_radio();
            set_upload_param(up, file.name, true);
        },

        UploadProgress: function (up, file) {
            var fileid = $('.onlyfile').data('id')
            var d = document.getElementById(fileid);
            d.getElementsByTagName('b')[0].innerHTML = '<span class="upspeed">' + file.percent + "%</span>";
            var prog = d.getElementsByTagName('div')[0];
            var progBar = prog.getElementsByTagName('div')[0]
            progBar.style.width = 2 * file.percent + 'px';
            progBar.setAttribute('aria-valuenow', file.percent);
        },

        FileUploaded: function (up, file, info) {
            if (info.status == 200) {
                document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name) + ' 回调服务器返回的内容是:' + info.response;
            } else if (info.status == 203) {
                document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '上传到OSS成功,但是oss访问用户设置的上传回调服务器失败,失败原因是:' + info.response;
            } else {
                document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response;
            }
        },

        Error: function (up, err) {
            if (err.code == -600) {
                document.getElementById('console').appendChild(document.createTextNode("\n选择的文件太大了,可以根据应用情况,在upload.js 设置一下上传的最大大小"));
            } else if (err.code == -601) {
                document.getElementById('console').appendChild(document.createTextNode("\n选择的文件后缀不对,可以根据应用情况,在upload.js进行设置可允许的上传文件类型"));
            } else if (err.code == -602) {
                document.getElementById('console').appendChild(document.createTextNode("\n这个文件已经上传过一遍了"));
            } else {
                document.getElementById('console').appendChild(document.createTextNode("\nError xml:" + err.response));
            }
        }
    }
})

uploader.init();

 

上一篇:关于跨域请求携带cookie和tp6文件上传


下一篇:composer版本回退