Javascript上传文件到阿里OSS存储,并支持进度查看

发布时间 2023-05-30 18:13:57作者: 第一夫人

现在使用js上传文件的插件有很多,例如:plupload等等

今天我记录一下使用原生js的上传文件,并且支持进度查看,下面直接上代码:

html代码:

<input type="file" onchange="uploadMedia(this)">
<a id="showProgress" style="display:none;" href="#"></a>

预览效果:

 javascript代码:

function uploadMedia(_this) {
        var $this= _this;
        document.getElementById("showProgress").style.display="inline-block";

        var xhr = new XMLHttpRequest();

        //上传进度
        xhr.upload.addEventListener("progress", function(evt){
            //console.log(evt);
            if (evt.lengthComputable) {
                //上传中设置上传的百分比
                var percentComplete = Math.round(evt.loaded * 100 / evt.total);
                if (percentComplete == 100) {
                    setTimeout(function () {
                        document.getElementById("showProgress").innerHTML = '已上传'+percentComplete+"%";
                    }, 500)
                } else {
                    document.getElementById("showProgress").innerHTML = '已上传'+percentComplete+"%";
                }
            } else {
                document.getElementById("showProgress").innerHTML = '无法计算';
            }
        }, false);

        //请求完成后执行的操作
        xhr.addEventListener("load", function(evt){
            var message = evt.target.responseText;
                obj = eval("("+message+")");
            alert('上传成功,地址为:'+obj.data.filename);
        }, false);

        //请求error
        xhr.addEventListener("error", uploadFailed, false);

        //请求中断
        xhr.addEventListener("abort", uploadCanceled, false);

        //参数转json
        var dataObj = JSON.parse(data);

        //设置请求参数
        var fd = new FormData();
        fd.append("OSSAccessKeyId", dataObj.OSSAccessKeyId);
        fd.append("Signature", dataObj.Signature);
        fd.append("callback", dataObj.callback);
        fd.append("expire", dataObj.expire);
        fd.append("key", dataObj.key);
        fd.append("name", $this.files[0].name);
        fd.append("policy", dataObj.policy);
        fd.append("file", $this.files[0]);

        //发送请求
        xhr.open("POST", 'https://'+dataObj.host);

        //发送数据
        xhr.send(fd);
    }

    function uploadFailed(evt) {
        alert("上传出错.");
    }

    function uploadCanceled(evt) {
        alert("上传已由用户或浏览器取消删除连接.");
    }

测试效果:

这里说明一下data的数据来源,因为我是使用的阿里OSS服务,先贴个demo数据看看

 其中name和file参数是js获取的文件对象里面的

贴下服务端的代码:

/**
* $object 为OSS上保存的文件路径和文件名,例如:media/2023/05/30/202305301747235055.mp4
*/
public function getUploadParams($object, $callbackUrl = '', $expire = 3600) { self::init(); if(!$callbackUrl){ $callbackUrl = self::$callbackUrl; } $callback_param = array( 'callbackUrl' => $callbackUrl, 'callbackBody' => 'filename=${object}&size=${size}&mimeType=${mimeType}&imageHeight=${imageInfo.height}&imageWidth=${imageInfo.width}', 'callbackBodyType' => "application/x-www-form-urlencoded" ); $callback_string = json_encode($callback_param); $base64_callback_body = base64_encode($callback_string); $now = time(); $end = $now + $expire; $expiration = self::gmt_iso8601($end); //最大文件大小.用户可以自己设置 $condition = array(0 => 'content-length-range', 1 => 0, 2 => 2684354560);//最大2.5G $conditions[] = $condition; //表示用户上传的数据,必须是以$dir开始, 不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录 $start = array(0 => 'eq', 1 => '$key', 2 => $object); $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, self::$access_secret, true)); $response = array(); $response['host'] = self::$endpoint_bucket; $response['key'] = $object; $response['OSSAccessKeyId'] = self::$access_id; $response['policy'] = $base64_policy; $response['Signature'] = $signature; $response['expire'] = $end; $response['callback'] = $base64_callback_body; return json_encode($response); } public static 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"; }

这里,我只贴了2个基础的方法,还有OSS的核心类,我没有贴出来,有兴趣的小伙伴,可以参考官方文档:https://help.aliyun.com/document_detail/31927.html?spm=a2c4g.31927.0.0.52a874ffER6VxX