項目的新需求是用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>
總結:官方文檔一定要好好看………………
