Javascript上传文件到阿里OSS存储,并支持进度查看
现在使用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