踩坑Webuploader視頻上傳

背景

因爲我司業務關係,需實現兼容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端上傳(視頻文件大的,分割的次數也越多)網絡

  • 第一步:根據視頻文件的總大小、設定每次分割視頻流的大小
  • 第二步:把視頻文件的md5字符串、
  • 視頻已上傳的大小值start(第一次是根據JS端認證的填寫,第二次是根據上一次返回的填寫)、分割的視頻流傳輸到upUrl
  • 返回json的參數:
  • success:驗證上傳該段視頻流是否成功
  • start:已上傳的大小

插件配置解析

HTML部分

首先準備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> 
複製代碼

初始化webuploader

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);
複製代碼

至此視頻上傳功能,基本能實現。

tips:

  • 彈出窗顯示上傳按鈕功能時,需注意初始化的時間以及銷燬 webuploader 實例,應當在modal顯示後,以及隱藏後回調處理。
  • 當實現多選文件上傳時,需匹配好上傳分塊時的參數
  • IE8瀏覽器彈窗顯示文件選擇按鈕可能會出現flash錯誤問題,只需在彈窗顯示徹底時,用樣式調整便可
相關文章
相關標籤/搜索