因爲我司業務關係,需實現兼容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);
複製代碼
至此視頻上傳功能,基本能實現。