WebUploader之前端大文件分片上传

WebUploader之单个大文件分片上传(前端实现)

1、组件简介

webuploader(官方定义):是一个以 HTML5 为主, Flash为辅的文件上传组件,采用大文件分片/并发上传的方式,极大地提高了文件上传的效率,同时兼容多种浏览器版本;

链接: WebUploader官网.

2、前端代码实现

首先,下载组件,并引入到项目文件;

import WebUploader from "webuploader";

WebUploader组件包

本例子模拟后台所需参数:

参数 说明
guid 文件分片GUID
md5Value 文件的 MD5值
chunk 当前所传文件的当前分片数
chunks 当前所传文件的分片总数
id 文件ID
fileName 文件名称
file 文件内容

话不多说,直接上代码。

//引入组件
import WebUploader from "webuploader";
let uploader = null,GUID = null;

onReady(){		
		GUID = WebUploader.Base.guid();//每个文件有自己唯一的guid
        uploader = WebUploader.create({
           //设置选完文件后是否自动上传
           auto: false,
           //swf文件路径
           // swf: 'vendor/webUpload/Uploader.swf',
           // 文件接收服务端。
           server: "http://www.baidu.com/BigFileUpload", //服务器端的上传页面地址
           // 选择文件的按钮。可选。
           // 内部根据当前运行是创建,可能是input元素,也可能是flash.
           pick: "#fileupload",//点击选择文件的按钮id
           chunked: true, //开启分块上传
           chunkSize: 10 * 1024 * 1024,//10M 一个分片
           chunkRetry: 3, //网络问题上传失败后重试次数
           threads: 1, //上传并发数
           //fileNumLimit :1,
           fileSizeLimit: 1000 * 1024 * 1024, //最大1GB
           fileSingleSizeLimit: 1000 * 1024 * 1024,
           resize: false,//不压缩
           formData: {},
           //选择文件类型
           accept: {
               title: 'Zip files',
               extensions: 'zip',
               mimeTypes: '.zip'
           },
       });

       // 当有文件被添加进队列的时候
       uploader.on("fileQueued", function (file) {
       		//进行是否采用分片上传判断
			if(file.size > 50*1024*1024){
				uploader.option.chunked = true;
			}else{ //文件的大小 小于 50M 则不采用分片上传
				uploader.option.chunked = false;
			}
       
			//md5计算
              uploader
                  .md5File(file)
                  .progress(function (percentage) {
                      // console.log("Percentage:", percentage);
                  })
                  // MD5计算完毕,可以点击上传了
                  .then(function (fileMd5) {
                      // 完成
                      file.wholeMd5 = fileMd5; //获取到了md5
                  });
       });

       // 文件上传过程中创建进度条实时显示。
       uploader.on("uploadProgress", function (file, percentage) {                
           if (percentage * 100 > 100) {
               return;
           }
           dialogUploadVm.progress = parseInt(percentage * 100);
       });
		
		// 当validate不通过时,会以派送错误事件的形式通知调用者。
       uploader.on("error", function (type) {                
           if (type == 'Q_EXCEED_SIZE_LIMIT') {
               notification.error({
                   message: '上传的文件大小不能超过1GB',
                   title: '通知'
               });
           }else if(type == 'Q_TYPE_DENIED') {//当文件类型不满足时触发
               notification.error({
                   message: '仅支持上传zip压缩文件',
                   title: '通知'
               });
           }
       });

       //发送前填充数据,主要用来询问是否要添加附带参数
       uploader.on("uploadBeforeSend", function (block, data) {
           // block为分块数据。
           console.log(block);
           console.log(data);                
           
           // file为分块对应的file对象。
           var file = block.file;
           var fileMd5 = file.wholeMd5;

           // 修改data可以控制发送哪些携带数据。
           // 将存在file对象中的md5数据携带发送过去。

           data.chunk = block.chunk;
           data.chunks = block.chunks;
           data.md5Value = fileMd5; //md5,文件的MD5值 
           data.id = file.id;//文件ID
           data.fileName = file.name;//文件名称
           // data.file = file;//当前所传分片
           data.guid = GUID;
           data.type = 0;

           // 删除其他数据(默认的上传字段)
           delete data.lastModifiedDate;
           delete data.size;
           delete data.name;           
       });

		//当文件上传成功时触发。
       uploader.on("uploadSuccess", function (file, response) {
       		//response {Object}服务端返回的数据
           if (response.code == 1602) {
               notification.error({
                   message: '上传失败,已存在最新版本的文件',
                   title: '通知'
               });
           } else if (response.code == 0) {
				//success
           } else {
               notification.warn({
                   message: response.msg,
                   title: '通知'
               });
               setTimeout(() => {
                   dialogUploadVm.progress = 0;
               }, 1500);
           }
       });
       
       //当文件上传出错时触发。
       uploader.on("uploadError", function (file, reason) {
       		//reason {String}出错的code
           notification.error({
               message: "上传出错,请重新上传",
               title: '通知'
           });
       });

		//上传完成后回调
       uploader.on("uploadComplete", function (file) {           
           uploader.reset();//重置uploader。目前只重置了队列。
       });

		//上传完后的回调方法
       uploader.on("uploadFinished", function () {           
           //提交表单
           uploader.reset();//重置uploader。目前只重置了队列。
       });
}      

//确定上传的时候执行此函数:
function okButton(){
	//假设拿到了需要额外上传的内容,比如 版本号,版本信息
	let inputJson = {
        "version": "",
        "updateInfo": "",
    };
    
	uploader.options.formData = {//这里可以设置组件外需要上传的参数
	     "type": 0,//与组件内部type参数冲突,若要使用需在 uploadBeforeSend 时修改 data.type;
	     "version": this.inputJson.version,
	     "changeLog": this.inputJson.updateInfo,
	};
	uploader.upload(); //上传
}

3、注意点

  1. 根据条件判断 是否采用分片上传 功能的代码需写在 “文件被添加进队列的时候”,即 fileQueued;如果在 “uploadBeforeSend” 时进行判断会无效。
  2. uploadBeforeSend 时进行组件相关参数赋值,不需要的组件默认自带参数用 delete 删除
  3. 设置组件外需要上传的参数,用 uploader.options.formData 进行赋值。
  4. 选择文件后可能会无法再次选择文件,需要 uploader.reset(); 重置一下队列。

4、传参情况

传参截图

5、目前遇到的一个坑

  • 点击按钮不会出现弹框
    模拟官方文档上传按钮,但是发现怎么点击都没反应,但是当按下 F12 时就可以点击。其实是WebUploader初始化的时候,封装了一个 input 标签,属性 type=‘file’。初始化的时候因为获取不到正确的自身或者容器的大小,这时候初始化出来的这个透明层的大小为 1px*1px,根本点不到,也就触发不了点击事件,只需要在css里面加上一段代码:
    按钮的html截图
#fileupload div:nth-child(2){
    width:100%!important;
    height:100%!important;
}
发布了1 篇原创文章 · 获赞 4 · 访问量 41

猜你喜欢

转载自blog.csdn.net/wealth_nana/article/details/105051649