【H5】手機瀏覽器分批次多張上傳圖片(檔案),包含進度條
阿新 • • 發佈:2019-01-07
描述
本文所描述的上傳檔案主要是應用於手機端,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事件獲取上傳的檔案。↑
2.繫結各種事件,進度條最關鍵需要講各個程序的進度累加 ↑<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>
4.進度條這是最大的難點,因為是非同步的結果需要保證每個批次的進度不要亂,放到陣列中這樣每個批次只會有一個最大的進度數字。用方法名稱開傳遞引數實屬無奈,因為這裡拿不到response。 ↑<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>
<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的問題處理好的就可以了,失敗的監聽事件跟成功的同理,不寫了 ↑總結
分批上傳可以避免圖片太多一次請求失敗全失敗的結果,而且速度也有提升,希望對大家有幫助。寫的不對的地方請指正