webuploader大文件分片,多线程总结
项目的新需求是用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>
总结:官方文档一定要好好看………………
webuploader大文件分片,多线程总结的更多相关文章
- Webuploader 大文件分片上传
百度Webuploader 大文件分片上传(.net接收) 前阵子要做个大文件上传的功能,找来找去发现Webuploader还不错,关于她的介绍我就不再赘述. 动手前,在园子里找到了一篇不错的分片 ...
- 使用Webuploader大文件分片传输
背景:50G大文件的HTTP上传至服务器. 好了,根据这个命题,可以开始研究我们怎么做才能把这么大的文件上传成功. 分片上传是肯定的,断点续传也是要有的,进度可视化那就更好了,基于这些,我选择了Web ...
- 百度Webuploader 大文件分片上传(.net接收)
前阵子要做个大文件上传的功能,找来找去发现Webuploader还不错,关于她的介绍我就不再赘述. 动手前,在园子里找到了一篇不错的分片上传的帖子,参考之后,踏出了第一步.此文记录我这次实践的点滴,仅 ...
- 百度Webuploader 大文件分片上传(.net接收)
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- asp.net mvc+webuploader大文件分片上传
首先是前端: var GUID = WebUploader.Base.guid();//一个GUID uploadereditsVideo = WebUploader.create({ // swf文 ...
- ASP.NET CORE使用WebUploader对大文件分片上传,并通过ASP.NET CORE SignalR实时反馈后台处理进度给前端展示
本次,我们来实现一个单个大文件上传,并且把后台对上传文件的处理进度通过ASP.NET CORE SignalR反馈给前端展示,比如上传一个大的zip压缩包文件,后台进行解压缩,并且对压缩包中的文件进行 ...
- .NetCore+WebUploader实现大文件分片上传
项目要求通过网站上传大文件,比如视频文件,通过摸索实现了文件分片来上传,然后后台进行合并. 使用了开源的前台上传插件WebUploader(http://fex.baidu.com/webupload ...
- thinkphp+webuploader实现大文件分片上传
大文件分片上传,简单来说就是把大文件切分为小文件,然后再一个一个的上传,到最后由这些小文件再合并成原来的文件 webuploader下载地址及其文档:http://fex.baidu.com/webu ...
- 在React中使用WebUploader实现大文件分片上传的踩坑日记!
前段时间公司项目有个大文件分片上传的需求,项目是用React写的,大文件分片上传这个功能使用了WebUploader这个组件. 具体交互是: 1. 点击上传文件button后出现弹窗,弹窗内有选择文件 ...
随机推荐
- 软件推荐【Windows】
随时更新...链接为官网,自用保证安全(不信任可以把鼠标放在超链接上预览一下) 如有备注,下载链接均为最新(因为都是官方自动更新的下载链) 首先: 推荐一个软件管家(毕竟有时外网不稳定, ...
- 问题查询-tomcat内存泄露
1.报警信息 内容: 微信服务器向公众号推送消息或事件后,开发者5秒内没有返回 次数: 5分钟 239次 错误样例: [OpenID=o][Stamp=1562718361][3rdUrl=url][ ...
- Debug 路漫漫-10:AttributeError: 'Embedding' object has no attribute 'get_shape'
CNN的Embedding层报错: 报错:AttributeError: 'Embedding' object has no attribute 'get_shape' 查了下是这个问题: https ...
- lock、tryLock和lockInterruptibly的差別
lock():若lock被thread A取得,thread B会进入block状态,直到取得lock:tryLock():若当下不能取得lock,thread就会放弃,可以设置一个超时时间参数,等待 ...
- Java程序使用Alpine Linux报错java.lang.NoClassDefFoundError: Could not initialize class org.xerial.snappy.Snappy解决
报错内容 Caused by: java.lang.UnsatisfiedLinkError: /tmp/snappy-1.1.7-4a4b576a-c34c-481e-b6ac-9b4abacb11 ...
- python 练习题:请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串
# -*- coding: utf-8 -*- # 请利用Python内置的hex()函数把一个整数转换成十六进制表示的字符串 n1 = 255 n2 = 1000 print(hex(n1)) pr ...
- html 图片滚动代码
我自己也在用的,网页常用!分享出来 最简单易懂源码 <!--下面是向上滚动代码--> <div id=butong_net_top style=overflow:hidden;hei ...
- saltstack手册(含官方pdf)
官方手册 https://docs.saltstack.com/en/pdf/Salt-2019.2.1.pdf 快速入门 SALTSTACK是什么? Salt是一种和以往不同的基础设施管理方法,它是 ...
- from import语句
*)假如导入出现了问题,那么一定是导入的文件里的语法问题或者其他问题 参考链接:http://www.cnblogs.com/hwf-73/p/5493328.html 1)导入时重命名 as fro ...
- Python基础15
P75. 闭包,需再理解. 装饰器,语法糖