项目的新需求是用webuploader来做一个多文件,多线程,并且可以进行分块上传的要求,这些在前面的一篇文章当中足够使用了,但是现在又来一个新的需求,要求上传失败的文件进行重新的上传……心里默默说句事儿真多
找了很多的资料,也看了官方的例子和文档,最后发现还是得细看官方的文档。
整体的思路是把上传失败的文件,展示出来,加一个重新上传的按钮,然后把这个文件重新进行上传
官方文档中uploader中有一个upload的方法,这个方法可以传file对象也可以传file的id的值
upload
- upload() ⇒ undefined
- upload( file | fileId) ⇒ undefined
开始上传。此方法可以从初始状态调用开始上传流程,也可以从暂停状态调用,继续上传流程。
可以指定开始某一个文件。
接下来就是如何获取到这个file的值了,如果你是单线程的话,我们可以在上传失败的地方利用 file.setStatus('error')这个方法,将所失败的文件的状态置为error,然后通过
uploader.getFiles('error')的方法,获取到这个文件,最后通过 uploader.upload(uploader.getFiles('error'));来上传这个文件。
之所以这样做的原因是,本身的uplaoder是有一个error的方法,然后执行uploader.retry()的方法直接可以进行重新上传,但是这个error的方法,是必须在你接口不存在的时候才会进入,一但你的分块的或者其他的接口已经进入了,其实这个时候默认的是你上传就已经成功了,所以才需要给这个文件设置为error的状态来进行标识。
如果你是多线程的那么这个时候,请你在这些文件一个个加载进来的时候,给他一个id的值,这个id的值就是你的file的id。以便后期可以进行标识。
我这边是因多线程的时候,在分块的时候,会不确定md5的值是否是一致的,所以写了一个数组,把这些文件的MD5的值放在这个数组里面,不管有多少个,始终都是先走第一个,然后第二个检查文件,第三个上传分块,所以要保证第二个检查的文件和第三个上传文件的分块是一致的就可以。每次在上传分块完成之后,num++;这样不管在第一个的接口位置进来了多少个file,第二个,第三个上传分块的接口都能够保证是同一个文件。
因为你要重新上传,所以要把这个数组的下标置为0,这个数组置为空。
然后通过uploader.upload的方法来进行id的指定文件的传递。
只是这样还不够,还需要点击上传才可以上传,但是实际的操作当中,为了用户体验,我们并不想让用户重新点击统一的那个按钮进行上传,需要用户点击每一个上传失败的重新上传按钮来进行上传,这个时候我们就可以使用trigger的方法,来通过点击重新上传来出发开始上传这个按钮的事件。使用trigger和triggerHandle的区别是,trigger执行两次因为冒泡,而triggerHandle执行一次,但是这个代码中我们要使用trigger事件,因为webuploader当中,点击一次是上传,还有一次是暂停,默认的上传完之后是暂停,所以要点击两次才可以进行上传。
然后通过以下的代码
//重新上传按钮的事件
$("body").on('click', '.retry', function() { var rindex = $(this).parents(".item-upload").index(); var deid = $('.item-upload').eq(rindex).attr("id");//file的id console.log(uploader.getFiles()); console.log(uploader.getFiles('error')); fnum = 0; fm=[]; //uploader.upload(uploader.getFiles('error')); uploader.upload(deid); //$("input[type='file']")[0].click(); $("#ctlBtn").trigger('click'); $("#ctlBtn").trigger('click'); });
完整的代码如下
<script src="/RRM/laydate/laydate.js"></script> <script type="text/javascript"> var date = new Date; var year = date.getFullYear(); laydate.render({ elem: '#info-year', type: 'year', value: year, icon: '1' //指定元素 }); </script> <script type="text/javascript"> jQuery(function() { var $ = jQuery, $list = $('#thelist'), $btn = $('#ctlBtn'), state = 'pending', uploader; var fileMd5; var createTime; var fileName; var flag = true; var dataState; var fnum = 0; var fm = []; var sutag = true; //监听分块上传过程中的三个时间点 WebUploader.Uploader.register({ "before-send-file": "beforeSendFile", "before-send": "beforeSend", "after-send-file": "afterSendFile", }, { //时间点1:所有分块进行上传之前调用此函数 beforeSendFile: function(file) { var startTime = new Date(file.lastModifiedDate); startTime = startTime.getTime(); createTime = startTime; fileName = file.name; /*fileName = encodeURI(fileName);*/ var deferred = WebUploader.Deferred(); //1、计算文件的唯一标记,用于断点续传 (new WebUploader.Uploader()).md5File(file, 0, 10 * 1024 * 1024) .progress(function(percentage) { console.log("正在读取文件"); }) .then(function(val) { fileMd5 = val; fm.push(fileMd5); console.log("成功获取文件信息……"); //获取文件信息后进入下一步 deferred.resolve(); }); return deferred.promise(); }, //时间点2:如果有分块上传,则每个分块上传之前调用此函数 beforeSend: function(block) { var deferred = WebUploader.Deferred(); $.ajax({ type: "POST", url: "/RRM/manager/file/checkFile", data: { //文件唯一标记 fileMd5: fm[fnum], //当前分块下标 chunk: block.chunk, //当前分块大小 chunkSize: block.end - block.start }, cache: false, async: false, dataType: "json", success: function(response) { if (response.ifExist) { //分块存在,跳过 deferred.reject(); } else { //分块不存在或不完整,重新发送该分块内容 deferred.resolve(); } } }); this.owner.options.formData.fileMd5 = fileMd5; this.owner.options.formData.chunk = block.chunk; deferred.resolve(); return deferred.promise(); }, //时间点3:所有分块上传成功后调用此函数 afterSendFile: function() { //如果分块上传成功,则通知后台合并分块 $.ajax({ type: "POST", url: "/RRM/manager/file/mergeChunks", data: { fileMd5: fm[fnum], name: fileName, taskName: taskName, taskId: taskId, resourceType: infocond, resourceKey: labelarr, resourcePlace: taskAdd, taskYear: infoyear, adminDivision: proarr, createTime: createTime }, cache: false, async: false, success: function(response) { fnum++; if (response.success == true) { dataState = response; console.log("上传分块成功"); flag = true; } else { console.log("上传分块失败"); flag = false; layer.closeAll('loading'); } }, error: function() { fnum++; dataState = undefined; var newTime = new Date(createTime); //就得到普通的时间了 console.log(newTime); console.log("上传分块失败"); flag = false; layer.closeAll('loading'); } }); } }); uploader = WebUploader.create({ // 不压缩image resize: false, // swf文件路径 swf: '/swf/Uploader.swf', // 文件接收服务端。 server: '/RRM//manager/file/uploadVideo', threads: '5', //同时运行5个线程传输 fileNumLimit: '6', //文件总数量只能选择10个 fileVal: 'file', //此属性是你提交的图片的name属性值,相当于<input type="file" name="userAvatar">,如果不设置,系统有默认值 method: 'POST', // 选择文件的按钮。可选。 // 内部根据当前运行是创建,可能是input元素,也可能是flash. pick: '#picker', //开启分片上传 //开启分片上传 chunked: true, chunkSize: 10 * 1024 * 1024, duplicate: true //允许重复上传 }); // 当有文件添加进来的时候 uploader.on('fileQueued', function(file) { // console.log(file); uptype = $("select[class='info-cond']").val(); var filetype = file.name; filetype = filetype.split('.'); filetype = filetype[filetype.length - 1]; filetype = filetype.toLowerCase(); //判断资源类型 //图片 if (uptype == '1') { if (filetype != 'png' && filetype != 'jpg' && filetype != 'jpeg' && filetype != 'bmp' && filetype != 'gif' && filetype != 'tif' && filetype != 'raw' && filetype != 'psd') { layer.alert("请上传符合标准的图片格式文件"); return false; } } //文本 if (uptype == '2') { if (filetype != 'txt' && filetype != 'docx' && filetype != 'xlsx' && filetype != 'ppt' && filetype != 'pdf' && filetype != 'pptx' && filetype != 'xls') { layer.alert("请上传符合标准的文档格式文件"); return false; } } //视频 if (uptype == '0') { if (filetype != 'flv' && filetype != 'avi') { layer.alert("请上传符合标准的视频格式文件"); return false; } } if (uptype == '3') { if (filetype != 'png' && filetype != 'jpg' && filetype != 'jpeg' && filetype != 'bmp' && filetype != 'gif' && filetype != 'tif' && filetype != 'raw' && filetype != 'psd') { layer.alert("请上传符合标准的证件照格式文件"); return false; } } $list.append('<div id="' + file.id + '" class="item-upload">' + '<h4 class="info clearfix"><p class="fleft">' + file.name + '</p><p class="state fright">等待上传...<i class="fa fa-times" aria-hidden="true"></i></p></h4>' + '</div>'); }); // 文件上传过程中创建进度条实时显示。 uploader.on('uploadProgress', function(file, percentage) { layer.load(); var $li = $('#' + file.id), $percent = $li.find('.progress .progress-bar'); // 避免重复创建 if (!$percent.length) { $percent = $('<div class="progress progress-striped active">' + '<div class="progress-bar" role="progressbar" style="width: 0%">' + '</div>' + '</div>').appendTo($li).find('.progress-bar'); } $li.find('p.state').text('上传中'); $percent.css('width', percentage * 100 + '%'); }); uploader.on('uploadSuccess', function(file) { //dataState = response; layer.closeAll('loading'); if (dataState == undefined) { $('#' + file.id).find('p.state').text('上传失败'); $('#' + file.id).find('button').remove(); $('#' + file.id).find('p.state').before('<button id="retry" type="button" class="btn btn-primary fright retry pbtn">重新上传</button>'); flag = false; sutag = flag; file.setStatus('error'); layer.closeAll('loading'); } if (dataState.success == true) { if (dataState.data > 0) { layer.alert("该文件已上传,请不要重复上传"); $('#' + file.id).find('p.state').text('已存在'); $('#' + file.id).find('button').remove(); flag = false; return false; } else { $('#' + file.id).find('p.state').text('已上传'); $('#' + file.id).find('button').remove(); } } else { $('#' + file.id).find('p.state').text('上传失败'); flag = false; } $('#uploader-demo').append('<input type="text" name="attachmentid" value="' + dataState.attachmentid + '"/>'); $('#' + file.id).addClass('upload-state-done'); }); // 所有文件上传成功后调用 uploader.on('uploadFinished', function(file) { //清空队列 layer.closeAll('tips'); layer.closeAll('loading'); uploader.reset(); if (sutag) { layer.alert("上传成功"); $(".uploader-list").children().remove(); $("input").val(""); $("input[type=file]").css("opacity", "0"); var date = new Date; var year = date.getFullYear(); laydate.render({ elem: '#info-year', type: 'year', value: year, icon: '1' //指定元素 }); $("select").val("0"); /*$("select[class='province'] option:gt(0)").remove();*/ $("select[class='city']").remove(); $("select[class='info-cond']").val("1"); $(".zclabel").remove(); labellist.length = 0; $.ajax({ type: 'GET', url: '/RRM/manager/app/getTaskInfo', dataType: 'json', data: {}, async: false, success: function(res) { $("select[class='taskName'] option").remove(); var len = res.data.length; if (len > 0) { var speop = '<option value="0">请选择</option>'; var spe = res.data; //专项 for (var i = 0; i < len; i++) { if (spe[i].parentCode != undefined && spe[i].parentCode != null) { speop += '<option value=' + spe[i].id + ',' + spe[i].parentCode + ',' + spe[i].cityCode + '>' + spe[i].name + '</option>'; } else { speop += '<option value=' + spe[i].id + ',' + spe[i].cityCode + '>' + spe[i].name + '</option>'; } } $("select[name=taskName]").append(speop); } }, error: function() { layer.alert("服务器正忙,请稍后再试"); } }); } }); uploader.on('uploadError', function(file) { $('#' + file.id).find('p.state').text('上传出错'); }); uploader.on('uploadComplete', function(file) { $('#' + file.id).find('.progress').fadeOut(); }); uploader.on('all', function(type) { if (type === 'startUpload') { state = 'uploading'; } else if (type === 'stopUpload') { state = 'paused'; } else if (type === 'uploadFinished') { state = 'done'; } if (state === 'uploading') { /* $btn.text('暂停上传');*/ } else { $btn.text('开始上传'); } }); //删除文件队列 $('.uploader-list').on('click', 'i', function() { var deid = $(this).parents('.item-upload').attr("id"); //删除队列中的文件 uploader.removeFile(deid, true); //删除节点 $(this).parents('.item-upload').remove(); }); //类型变换时 $("select[class='info-cond']").change(function() { //清空队列 uploader.reset(); //清空数据 $(".uploader-list").children().remove(); //console.log(uploader.getFiles()); }); var proarr; var labelarr; var infocond; var infoyear; var taskName; var taskId; var taskAdd; $btn.on('click', function() { proarr = ''; //省市县的字符串 labelarr = ''; infocond = $("select[class='info-cond']").val(); //资源类型 infoyear = $("input[id='info-year']").val(); //任务年份 taskName = $("select[class='taskName']").find('option:selected').text(); //资源名称 taskName = $.trim(taskName); taskAdd = $("input[name=taskAdd]").val(); //地点 taskId = $("select[class='taskName']").find('option:selected').val(); if (taskId != undefined) { taskId = taskId.split(','); taskId = taskId[0]; } //行政区域 var provin = $("select[class='province']").find('option:selected').val(); var cityvin = $("select[class='city']").find('option:selected').val(); if (cityvin != undefined && provin != undefined) { proarr = provin + ',' + cityvin + ',0'; } if (cityvin == undefined && provin == '') { proarr = '0,0,0'; } else if (cityvin == undefined) { proarr = provin + ',0,0'; } if (infoyear == '') { layer.msg("请上传年份"); return false; } if (taskAdd == '') { layer.msg("请将资源信息填写完整"); return false; } if (taskName == '请选择') { taskName = ''; taskId = ''; } //文件的判断 var filelen = $(".item-upload").length; if (filelen == '0') { layer.msg("请选择需要上传的文件"); return false; } if (labellist.length == 0) { layer.msg("请至少增加一个关键字标签"); return false; } //填充数据 labelarr = labellist.join(','); //判断 /*uploader.option('formData', { taskName: taskName, taskId: taskId, resourceType: infocond, resourceKey: labelarr, resourcePlace: taskAdd, taskYear: infoyear, adminDivision: proarr });*/ //console.log(uploader.options); if (state === 'uploading') { uploader.stop(); } else { uploader.upload(); } }); $("body").on('click', '.retry', function() { var rindex = $(this).parents(".item-upload").index(); var deid = $('.item-upload').eq(rindex).attr("id"); console.log(uploader.getFiles()); console.log(uploader.getFiles('error')); fnum = 0; fm=[]; //uploader.upload(uploader.getFiles('error')); uploader.upload(deid); //$("input[type='file']")[0].click(); $("#ctlBtn").trigger('click'); $("#ctlBtn").trigger('click'); }); }); </script> </body> </html>
总结:官方文档一定要好好看………………