因为我司业务关系,需实现兼容IE8+浏览器的视频上传功能,且支持多选断点上传。故借助Baidu WebFE(FEX)团队开发的webuploader文件上传插件实现此业务功能。javascript
1.js端认证(主要是判断视频是否已存在,若已存在,返回视频已上传的文件大小,只须要判断一次):html
第一步:计算视频文件的md5,视频文件越大、计算md5的时间越久html5
第二步:获取视频文件的总大小java
第三步:把视频名称、文件总大小、视频文件的md5字符串传输到tokenUrlweb
2.返回json的参数:json
success:验证是否成功promise
fileMd5:视频文件md5浏览器
start:已上传的大小(没上传过的返回0,已上传部分则返回对应已上传的大小值,例如:30000字节,已上传20000字节,则返回20000)bash
3.验证经过后,js端上传(视频文件大的,分割的次数也越多)网络
首先准备dom结构,包含存放文件信息的容器、选择按钮和上传按钮三个部分。
<!--视频列表显示-->
<ul class="resources_body_modal_add_list">
{#list queuedList as item}
<li class="resources_body_modal_add_list_item">
<div class="resources_body_modal_add_list_item_hd" style="background-image: url({item.gvdPic})"></div>
<div class="resources_body_modal_add_list_item_bd">
<input type="text" name="" placeholder="此处为视频名称,点击可修改" class="form-control" value={item.name} on-blur={this.updateName(item_index, $event)} />
</div>
<span class="resources_body_modal_add_list_item_icon" on-click={this.deleteQueuedFile(item_index)}>x</span>
<div class="resources_body_modal_add_list_item_bar">
<div class="resources_body_modal_add_list_item_bar_progress"></div>
</div>
</li>
{/list}
</ul>
<!--文件上传按钮-->
<div class="resources_body_modal_add_field">
<div class="resources_body_modal_add_field_cell">
<!--配置所用id-->
<div id="filePicker" class="resources_body_modal_add_field_cell_icon" r-hide={queuedList.length == queuedLimit}>+</div>
<p class="g-mb20" r-hide={queuedList.length == queuedLimit}>点击上传视频</p>
<p r-hide={queuedList.length} class="js-empty">每次最多上传{queuedLimit}个,单个视频不超过4G</p>
<p r-hide={!queuedList.length} class="js-full">
已选择
<span class="js-uploadLength"></span>个,
<span class="js-uploadLeft"></span>
</p>
</div>
</div>
复制代码
uploader = WebUploader.create({
resize: false, // 不压缩image
swf: base_URL + 'jslib/WebUploader/Uploader.swf', // swf文件路径
method: "post",
sendAsBinary : true,//文件上传二进制流
fileNumLimit: 10,//验证文件总数量, 超出则不容许加入队列
fileSingleSizeLimit: 4*1024*1024*1024,//验证单个文件大小是否超出限制, 超出则不容许加入队列
server: upload_URL,// 文件接收服务端
pick: {
id: '#filePicker', //这个id是你要点击上传文件按钮的外层div的id
multiple : true //是否能够批量上传,true能够同时选择多个文件
},
chunked: true,//是否要分片处理大文件上传
threads: true, //上传并发数
chunkSize:3*1024*1024, //分片上传,每片2M,默认是5M
prepareNextFile: true,//上传当前分片时预处理下一分片
//auto: false //选择文件后是否自动上传
chunkRetry : 1, //若是某个分片因为网络问题出错,容许自动重传次数
duplicate: false, //重复选择
// runtimeOrder: 'html5, flash'
accept: {
extensions: 'avi,wmv,rm,rmvb,mov,mkv,flv,mp4,f4v,3gp,ts,wma,wav,aac',
mimeTypes: '.avi,.wmv,.rm,.rmvb,.mov,.mkv,.flv,.mp4,.f4v,.3gp,.ts,.wma,.wav,.aac'
}//视频文件后缀
});
复制代码
WebUploader.Uploader.register({
"before-send-file":"beforeSendFile",
"before-send":"beforeSend",
"after-send-file":"afterSendFile",
},{
//时间点1:全部分块进行上传以前调用此函数
beforeSendFile:function(file){
var deferred = WebUploader.Deferred();
//一、计算文件的惟一标记,用于断点续传
(new WebUploader.Uploader()).md5File(file,0,2*1024*1024)
.progress(function(percentage){
})
.then(function(val){
fileMd5=val;
//获取文件信息后进入下一步
deferred.resolve();
});
return deferred.promise();
},
//时间点2:若是有分块上传,则每一个分块上传以前调用此函数
beforeSend:function(block){
var deferred = WebUploader.Deferred();
if(videoAdd[block.file.id] > block.start){
// 分块存在,跳过
deferred.reject();
}else{
// 分块不存在或不完整,从新发送该分块内容
this.owner.options.formData={
start: block.start,//设置视频上传的start点
fileMd5: videoMd5[block.file.id]//设置视频上传的惟一标识MD5
}
deferred.resolve();
}
return deferred.promise();
},
//时间点3:全部分块上传成功后调用此函数
afterSendFile:function(file, response){
//分块上传成功,执行成功回调
successHandler(file, response, fileArr);
}
});
复制代码
监听fileQueued事件来实现
uploader.on( 'fileQueued', function( file ) {
// 符合条件的视频才会加进队列,包括大小,后缀,数量限制
//设置文件loading状态
uploader.md5File(file)
// 及时显示进度
.progress(function(percentage) {
//可根据percentage显示获取文件信息时的进度
})
//完成
.then(function(md5Val){
//开始执行上传操做
})
})
复制代码
//显示文件上传进度
uploader.on( 'uploadProgress', function(file, percentage) {
var $uploading= $('.js-uploading-'+file.id);
var progressWid= (percentage*100)+'%';
$uploading.find('.js-bar').width(progressWid);
});
复制代码
//文件上传失败处理
uploader.on( 'uploadError', function(file, reason) {
$('.js-uploading-'+file.id).addClass('hidden');
uploader.cancelFile(file);//清空队列占位
});
复制代码
uploader.on('error', errorHandler);
复制代码
至此视频上传功能,基本能实现。