webuploader单文件分片上传,断点续传前端案例

在这里插入图片描述

需求不同,思路相同,可借鉴,无法直接使用
实现思路
  1. 调用接口,回显,状态为正在上传的改为上传中断 第132行
  2. 上传文件,调用接口判断文件是否存在 ,当前上传到第几片。 第207行
  3. 如果上传过,并且中断,从指定切片开始上传 第212行
  4. 上传面板列表添加文件进度 第334行
  5. 上传完第一片后,前端存储后台上传接口返回的唯一id,下片传入,后台更新库更方便 第343行
  6. 上传文件成功/失败后,修改按钮、进度条等文字样式 第349行
上传面板样式

文件分为上传完成、上传中断、正在上传、任务暂停、上传失败等几个状态
在这里插入图片描述

上传面板template模板

因为jsp中语法<%%>占用,需要将template.js中<% %>改为 {{ }}

<script type="text/html" id="upload-tel">
{{for(var i=0;i<data.length;i++){ }}
{{var item = data[i]}}
{{if(item.isShow){ }}
    <li class="clear" dbid="{{=item.dbId}}" md5="{{=item.md5Value}}">
{{ } }}
{{if(!item.isShow){ }}
    <li class="clear" style="display:none" dbid="{{=item.dbId}}" md5="{{=item.md5Value}}">
{{ } }}
        <div class="list-left">
            <p class="clear">
                <span class="file-name" title="{{=item.name}}">{{=item.name}}</span>
                <span class="upload-status" status="{{=item.status}}">{{=item.statusText}}</span>
            </p>
            <div class="progress {{=item.barClass}}">
                <div class="bar" style="width: {{=item.progress}}"></div>
            </div>
        </div>
        <div class="list-right">
            <span class="progressText">{{=item.progress}}</span>
            <span class="size" title="{{=item.overSize}}/{{=item.fakeSize}}{{=item.company}}">
				<span>{{=item.overSize}}</span>
				/
				<span>{{=item.fakeSize}}</span>
				<span>{{=item.company}}</span>
			</span>
            {{if (item.status == "1") { }}
                <input type="button" class="btn btn-link pause" value="暂停">
            {{ }else if (item.status == "-1") { }}
            	<input type="button" class="btn btn-link start" value="开始">
            {{ }else if (item.status == "0" || item.status == "3") { }}
            	<input type="button" class="btn btn-link reup" value="重传">
			{{ } }}
            <input type="button" class="btn btn-link delete" value="删除">
        </div>
    </li>
{{ } }}
				</script>
全代码展示
//定义layer
var layer
layui.use('layer',function(){
	layer = layui.layer
})
//打开上传面板
function showUploadBox(){
	layer.open({
		type: 1,
		area: ['600px', '450px'],
		title: "上传文件列表",
		fixed: false, //不固定
		maxmin: true,
		shade:0,
		content: $('#upload-box'),
		success:function(layero){
	        layero.find('.layui-layer-max').hide(); //去掉最大化按钮
		},
		min:function(layero){
	        layero.find('.layui-layer-max').css('display','inline-block'); //去掉最大化按钮
		},
		restore:function(layero){
	        layero.find('.layui-layer-max').hide(); //去掉最大化按钮
		}
	});
}
//重传按钮绑定点击事件
function reuploadClick($li){
	$li.on("click",'.reup',function(){
		layer.msg('选择文件名为 <span style="color:red">'+$li.find('.file-name').text()+'</span>的文件,即可续传。',function(){
			$("#upload-btn input").click()
		})
	})
}
//删除按钮绑定点击事件
function deleteClick($li, file, uploader){
	$li.find('.delete').click(function(){
		clearUploader(file, uploader)
	})
}
//开始、暂停绑定点击事件
function playClick($li, uploader, file){
	$li.on('click', '.pause',function(){
		uploader.stop(file)
		$li.find('.pause').addClass('start').removeClass('pause').val('开始')
 	   .end().find('.upload-status').text('任务暂停').attr('status', "0")
	       .end().find('.progress').attr('class','').addClass('progress')
	})
	$li.on('click', '.start',function(){
		uploader.upload(file)
		$li.find('.start').addClass('pause').removeClass('start').val('暂停')
    	   .end().find('.upload-status').text('正在上传').attr('status', "1")
  	       .end().find('.progress').attr('class','').addClass('progress uploading')
	})
}
//渲染下载列表
function drawList(data, fake){
	var tpl = $('#upload-tel').html();
	if (data && data.length > 0){
		data.forEach(function(e,i){
			e.isShow = e.isShow == 0? false : true;
			// 转换状态
			switch(e.status){
			case "0":
				e.statusText = "等待上传";break;
			case "1":
				e.statusText = "正在上传";
				e.barClass = "uploading";break;
			case "-1":
				e.statusText = "上传失败";
				e.barClass = "upload-fail";break;
			case "2":
				e.statusText = "上传完成";
				e.barClass = "uploader";break;
			case "3":
				e.statusText = "上传中断";
				e.barClass = "upload-fail";break;
			}
			// 是否需要转换文件大小单位
			if (fake){
				var sizeCompany = computeSize(e.size)
				e.company = sizeCompany.company
				e.fakeSize = sizeCompany.fakeSize
			}
			// 上传完成赋值百分百,否则通过切片和切片大小计算百分比
			if (e.status == "2"){
				e.progress = "100%";
				e.overSize = e.fakeSize;
			} else {
				e.progress = ((e.chunk+1)/e.chunks * 100).toFixed(1) + '%'
				if(e.company == "GB"){
					e.overSize = (50 * 1024 * 1024 *(e.chunk+1)/1024/1024/1024).toFixed(1)
				}else if(e.company == "MB"){
					e.overSize = (50 * 1024 * 1024 *(e.chunk+1)/1024/1024).toFixed(1)
				}else {
					e.overSize = (50 * 1024 * 1024 *(e.chunk+1)/1024).toFixed(1)
				}
			}
		})
		// 渲染页面
		$("#upload-box ul").prepend(template(tpl, {data:data}))
	}
}
//计算文件适应单位和大小
function computeSize(size) {
	if(size > 1024 * 1024 * 1024){
		fakeSize = (size/1024/1024/1024).toFixed(1)
		company = "GB"
	}else if(size > 1024*1024){
		fakeSize = (size/1024/1024).toFixed(1)
		company = "MB"
	}else {
		fakeSize = (size/1024).toFixed(1)
		company = "KB"
	}
	return {fakeSize, company}
}
//检查文件
function checkFile(dbId="", name="", size="", md5Value="", successFnc){
	$.ajax({
		url: ctx+'/fileinfo/fileInfo/check',
		type:"POST",
		data: {
			'size': size,
			'md5Value': md5Value,
			'dbId': dbId
		},
		success:successFnc
	})
}
//获取上传列表,回显
function getUploadList(uploader){
	$.ajax({
		url: ctx+'/fileinfo/fileInfo/fileList',
		success:function(res){
			if(res && res.length > 0){
				res.forEach(function(e,i){
					if(e.status == "1"){
						e.status = "3"
					}
				})
				drawList(res, true)
				res.forEach(function(e,i){
		        	var $li = $('li[md5='+e.md5Value+']')
		        	deleteClick($li, {md5Value: e.md5Value, name: e.name,size: e.size}, uploader)
		        	reuploadClick($li)
				})
			}
		}
	})
}
//删除任务
function clearUploader(data, uploader){
	// 如果数据包含MD5属性,删除单个文件,否则清除全部完成文件
	if (data.md5Value || data.wholeMd5){
		var $li = $('li[md5='+(data.md5Value?data.md5Value:data.wholeMd5)+']')
		var dbid = $li.attr('dbid')
		var loading = layer.load(1, {shade: 0.5})
		$.ajax({
			url: ctx+'/fileinfo/fileInfo/clear',
			type: "POST",
			data:{
				md5: data.md5Value?data.md5Value:data.wholeMd5,
				size: data.size,
				dbId: dbid?dbid:""
			},
			success:function(res){
				// 如果此文件正在上传,移出上传列表
				if(data.id)uploader.removeFile(data)
				
				$li.hide();
				layer.close(loading)
				layer.msg("删除 "+data.name+" 成功")
			},
			error:function(){
				layer.close(loading)
				layer.msg('删除失败',{icon: 2})
			}
		})
	}else{
		$.ajax({
			url: ctx+'/fileinfo/fileInfo/clear',
			success:function(res){
				$("#upload-box .uploader").parents('li').hide();
				layer.msg("清除已完成任务成功")
			}
		})
	}
}
$(function () {
//	刷新提示
    window.addEventListener('beforeunload', function (event) {
//    	谷歌浏览器不支持设置文字内容,ie下会提示此段文字
        event.returnValue = '刷新或关闭页面会导致上传中断,之后继续上传需要重新选择文件。'
    })
    // 清除全部完成任务按钮事件
	$('#upload-box>input').click(clearUploader)
	// HOOK 这个必须要再uploader实例化前面
    WebUploader.Uploader.register({
        'before-send-file': 'beforeSendFile',//整个文件上传前
        'before-send': 'beforeSend' //每个分片上传前
    }, {
        beforeSendFile: function (file) {
            var deferred = WebUploader.Deferred();
        	var $li = $('li[md5='+file.wholeMd5+']')
        	// 检查接口,判断文件是否存在,上传到哪片
            checkFile($li.attr('dbid'), file.name, file.size, file.wholeMd5, function(res){
            	if (res.data && res.data.status == 2) {
        			layer.msg('文件已存在',{icon: 2})
					deferred.reject();
            	} else {
                    file.startChunk = res.data.chunk
					deferred.resolve();
            	}
            })
            return deferred.promise();
        },
        beforeSend: function (block) {
            var doneChunkPartIndex = block.file.startChunk;//获取已经上传过的下标
            var deferred = WebUploader.Deferred();
            if(doneChunkPartIndex>0){
                if(block.chunk>doneChunkPartIndex){
                    //分块不存在,重新发送该分块内容
                    deferred.resolve();
                }else{
                    //分块存在,跳过
                    deferred.reject();
                }
            }else{
                //分块不存在,重新发送该分块内容
                deferred.resolve();
            }
            return deferred.promise();
        }
    });
    var uploader = WebUploader.create({
        //设置选完文件后是否自动上传
        auto: false,
        // 文件接收服务端。
        swf: ctxStatic+'webuploader/dist/Uploader.swf', // flash上传
        server: ctx+'/fileinfo/fileInfo/upload',
        // 选择文件的按钮。可选。
        // 内部根据当前运行是创建,可能是input元素,也可能是flash.
        pick: '#upload-btn',
        chunked: true, //开启分块上传
        chunkSize: 50*1024*1024, // 50MB 每片大小 单位B 如果文件小于每片大小限制,不会分片
        chunkRetry: 3,//网络问题上传失败后重试次数
        threads: 1, //上传并发数
        //fileNumLimit :1,
        fileSizeLimit: 10 * 1024 * 1024 * 1024 * 1024,// 10T 文件总大小限制 单位B
        fileSingleSizeLimit: 1024 * 1024 * 1024 * 1024,// 1T 单个文件大小限制 单位B
        resize: false//不压缩
        //选择文件类型
        //accept: {
        //    title: 'Video',
        //    extensions: 'mp4,avi',
        //    mimeTypes: 'video/*'
        //}
    });
//	window.onbeforeunload = function(){
//		layer.confirm("",function(){
//			uploader.getFiles('progressNum')
//		})
//		return false
//	}
	getUploadList(uploader);
    // 当有文件被添加进队列的时候
    uploader.on('fileQueued', function (file) {
        //md5计算
    	var loading = layer.load(1,{shade: 0.5})
        uploader.md5File(file).then(function (fileMd5) { // 完成
        	layer.close(loading)
            var end = +new Date();
			var sizeCompany = computeSize(file.size)
			// file添加属性
			file.company = sizeCompany.company
			file.fakeSize = sizeCompany.fakeSize
            file.wholeMd5 = fileMd5;//获取到了md5
            uploader.options.formData.md5Value = file.wholeMd5;//每个文件都附带一个md5,便于实现秒传
        	var $li = $('li[md5='+file.wholeMd5+']')
        	// 如果当前文件已存在,修改状态,按钮文字,进度条颜色
        	if ($li.length > 0){
        		file.dbId = $li.attr('dbid')
        		var status = $li.find('.upload-status').attr('status')
        		file.status = status=="3"?"1":status;
        		$li.find('.reup').addClass('pause').removeClass('reup').val('暂停')
            	$li.find('.upload-status').text('正在上传').attr('status', "1")
         	   .end().find('.progress').attr('class','').addClass('progress uploading')
         	   playClick($li, uploader, file);
        	}
            uploader.upload();
        });
    });
    //发送前填充数据
    uploader.on( 'uploadBeforeSend', function( block, data ) {
        // file为分块对应的file对象。
        var file = block.file;
        var fileMd5 = file.wholeMd5;
        // 修改data可以控制发送哪些携带数据。
        
        // 将存在file对象中的md5数据携带发送过去。
        data.md5Value = fileMd5;//md5
        data.dbId = file.dbId?file.dbId:""
        // 删除其他数据
        if(block.chunks>1){ //文件大于chunksize 分片上传 1:分片;0:不分片
            data.isChunked = 1;
        }else{
            data.isChunked = 0;
        }
    });
    // 文件上传过程中创建进度条实时显示。
    uploader.on('uploadProgress', function (file, percentage) {
    	var $li = $('li[md5='+file.wholeMd5+']')
//    	列表存在文件,只更新进度
    	if ($li && $li.length>0){
    		$li.find('.bar').css('width',(percentage*100).toFixed(1)+'%')
    		   .end().find('.progressText').text((percentage*100).toFixed(1)+'%')
    		   .end().find('.size>span').eq(0).text((file.fakeSize*percentage).toFixed(1))
    	} else {
//    		新增列表,默认参数
    		var data = [{
				isShow:true,
				id:file.id,
				md5Value:file.wholeMd5,
				name:file.name,
				status:"1",
				overSize:0,
				company:file.company,
				fakeSize:file.fakeSize,
				chunk:-1,
				chunks:1,
				dbId: ""
    		}]
    		drawList(data);
        	var $li = $('li[md5='+file.wholeMd5+']')
        	playClick($li, uploader, file);
        	deleteClick($li, file, uploader)
        	reuploadClick($li)
    		//showUploadBox();
    	}
    });
//    分片上传成功
    uploader.on('uploadAccept', function (object, ret) {
    	var $li = $('li[md5='+object.file.wholeMd5+']')
    	$li.attr("dbid", ret.dbId)
    	object.file.dbId = ret.dbId
    });
//    上传成功
    uploader.on('uploadSuccess', function (file) {
    	$('#upload-btn input').val('')
    	var $li = $('li[md5='+file.wholeMd5+']')
    	$li.find('.upload-status').text('上传完成')
    	   .end().find('.progressText').text('√').css('color','green')
    	   .end().find('.progress').attr('class','').addClass('progress uploader')
    	   .end().find('.size').next().remove()
    	var fileList = [];
    	
    	$(document).find("iframe")[0].contentWindow.$("td[data-field='dbId']").each(function(index,data){
    		fileList.push($(data).text());
    	})
    	fileList.push($li.attr("dbId"));
    	var fileJson = JSON.stringify(fileList);
    	var url = ctx+ "/fileinfo/fileInfo/fileSecList";
        $(document).find("iframe")[0].contentWindow.fileTable.reload({url, where: {"fileJson": fileJson}})
    });
//    上传出错
    uploader.on('uploadError', function (file) {
    	$('#upload-btn input').val('')
    	var $li = $('li[md5='+file.wholeMd5+']')
    	$li.find('.upload-status').text('上传失败')
    	   .end().find('.progressText').text('×').css('color','red')
    	   .end().find('.progress').attr('class','').addClass('progress upload-fail')
    	   .end().find('.size').next().removeClass('pause').removeClass('start').addClass('reup').val('重传')
    });
});


在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值