項目的新需求是用webuploader來作一個多文件,多線程,而且能夠進行分塊上傳的要求,這些在前面的一篇文章當中足夠使用了,可是如今又來一個新的需求,要求上傳失敗的文件進行從新的上傳……內心默默說句事兒真多javascript
找了不少的資料,也看了官方的例子和文檔,最後發現仍是得細看官方的文檔。css
總體的思路是把上傳失敗的文件,展現出來,加一個從新上傳的按鈕,而後把這個文件從新進行上傳html
官方文檔中uploader中有一個upload的方法,這個方法能夠傳file對象也能夠傳file的id的值java
開始上傳。此方法能夠從初始狀態調用開始上傳流程,也能夠從暫停狀態調用,繼續上傳流程。web
能夠指定開始某一個文件。ajax
接下來就是如何獲取到這個file的值了,若是你是單線程的話,咱們能夠在上傳失敗的地方利用 file.setStatus('error')這個方法,將所失敗的文件的狀態置爲error,而後經過json
uploader.getFiles('error')的方法,獲取到這個文件,最後經過 uploader.upload(uploader.getFiles('error'));來上傳這個文件。數組
之因此這樣作的緣由是,自己的uplaoder是有一個error的方法,而後執行uploader.retry()的方法直接能夠進行從新上傳,可是這個error的方法,是必須在你接口不存在的時候纔會進入,一但你的分塊的或者其餘的接口已經進入了,其實這個時候默認的是你上傳就已經成功了,因此才須要給這個文件設置爲error的狀態來進行標識。promise
若是你是多線程的那麼這個時候,請你在這些文件一個個加載進來的時候,給他一個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(); //一、計算文件的惟一標記,用於斷點續傳 (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>
總結:官方文檔必定要好好看………………