1. 程式人生 > >【H5】手機瀏覽器分批次多張上傳圖片(檔案),包含進度條

【H5】手機瀏覽器分批次多張上傳圖片(檔案),包含進度條

描述

本文所描述的上傳檔案主要是應用於手機端,PC端可以酌情改造。

應用場景:

手機瀏覽器一次上傳多張圖片或者檔案,將檔案每5個拆分為一組上傳。上傳進度條為手機端上傳至後臺所用時間不包含後臺耗時。

選擇圖片用H5的input file標籤(能否選多張看瀏覽器了),上傳功能使用XMLHttpRequest後面簡稱xhr,jquery和zepto中都包含。

html

<span style="font-size:14px;"><div id="uploadBtn" class="needsclick"><span class="needsclick">上傳照片</span></div>
<input type="file" id="uploadFile" name="uploadFile" multiple="multiple" accept="image/*" style="display: none"/></span>

1.將uploadBtn的點選事件繫結到file的點選事件上(這部分不多說),監聽file的onchange事件獲取上傳的檔案。
<span style="font-size:14px;">    var batchCount = 1;
    var batchNum = 5;
    var loadArr = [];
    $(function() {
        /**
         * file的onchange事件,處理上傳完成後的資料
         */
        $('#uploadFile').on('change', function(){
            var files = $('#uploadFile').prop('files');
            var allFileCount = files.length;
            if(files.length == 0){
                return;
            }
            var fd;
            // 計算一共會分成幾個批次
            batchCount = Math.ceil(allFileCount/batchNum);
            for(var i = 0;i < allFileCount; i++){
                if(i%batchNum == 0){
                    fd = new FormData();
                }
                if((i+1)%batchNum == 0 || (i+1) == allFileCount){
                    //監聽事件
                    var xhr = new XMLHttpRequest();
                    if((i+1) == allFileCount){
                        var funNum = batchCount -1;
                    }else{
                        var funNum = (i- (batchNum -1))/batchNum;
                    }
                    <span style="color:#CC0000;">var c = "printFunName"+funNum; //根據不同的名字區分屬於哪個批次(不能純數字),否則批次會亂
                    eval("function "+c+"(evt){uploadProgress(evt);}");
                    xhr.upload.onprogress = eval(c);//繫結進度條事件</span>
                    xhr.onload = function(evt){ // 載入完成事件,包含502等結果需要判斷狀態
                        loadSuccess(evt);
                    };
                    xhr.onerror = function(){ // 載入error事件
                        loadError(evt);
                    }
                    //傳送檔案和表單自定義引數
                    xhr.open("POST", "/photo/uploadFile",true);// 設定請求地址,true表示非同步,反之...

                    xhr.send(fd); // 傳送請求
                }
            }
        });</span>
2.繫結各種事件,進度條最關鍵需要講各個程序的進度累加  
<span style="font-size:14px;">    /**
     * 載入進度方法
     * @param evt
     */
    var progressArr = [];
    function uploadProgress(evt){
        if (evt.lengthComputable) {// 判斷是否有進度
            <span style="color:#FF0000;">var funName = evt.currentTarget.onprogress.name; // 實在是沒發傳參了,只好用這個了,有好的方法可以留言
            var funIndex = funName.substr(12);// 擷取方法名的字串後的數字,用來判斷是哪個批次的
            //evt.loaded:檔案上傳的大小 evt.total:檔案總的大小
            var percentComplete = Math.round((evt.loaded / evt.total) * 100);
            progressArr[funIndex] = percentComplete; // 把當前進度放進一個數組裡
            var prpgressTotal = 0;
            for(var i = 0; i < progressArr.length; i++){ // 遍歷陣列所有的進度,相加
                if(progressArr[i] != "" || progressArr[i] != undefined || progressArr[i] != 0){
                    prpgressTotal = prpgressTotal + progressArr[i];//一次上傳圖片分了4批這裡相加的結果在0--400之間
                }
            }
            //載入進度條,同時顯示資訊,這個位置要除以批次數量,假如最大400除以4個批次就是100%,四捨五入小數點
            var str  = '' + Math.round(prpgressTotal / batchCount) + '%';
            // str就是一個百分比的字串,自己展示出來即可
        }
    }</span>
4.進度條這是最大的難點,因為是非同步的結果需要保證每個批次的進度不要亂,放到陣列中這樣每個批次只會有一個最大的進度數字。用方法名稱開傳遞引數實屬無奈,因為這裡拿不到response。 ↑
<span style="color:#000000;">    /**
     * 上傳檔案成功事件
     */
    function loadSuccess(evt){
        var loadNum; //積累批次
        if(evt.target.status == 200){ // 200成功
            var jsonData = JSON.parse(evt.target.response); 
            loadNum = loadArr.push(jsonData);// 每次把response的資料保留,所有批次都到了一起處理,可以單獨顯示結果
           // 其中出現錯誤的請求要記錄,要不後面不知道一種成功了幾張,一個error表示一個批次都錯誤
            loadNum = loadArr.push("error");
        }
        if(loadNum == batchCount){ // 批次數等於完成的總數時就是所有資料都有結果了
            buildMessage(); // 自行處理loadArr中的結果,全域性變數
        }
    }
5.處理返回結果主要是把error的問題處理好的就可以了,失敗的監聽事件跟成功的同理,不寫了 ↑

總結

分批上傳可以避免圖片太多一次請求失敗全失敗的結果,而且速度也有提升,希望對大家有幫助。寫的不對的地方請指正