網頁內實現大檔案分片上傳、斷點續傳
阿新 • • 發佈:2018-12-11
最近做公司的專案,需要在後臺控制系統中新增一個功能-------向伺服器傳送程式更新包;這些程式更新包大小不固定,但基本都在1G到4G之間,剛開始還真是難倒我了,因為之前的專案中沒有上傳過這麼大的檔案,還要斷點續傳,後來經過查資料,寫DEMO,這個問題終於解決了;
解決辦法:
使用XMLHttpRequest來實現,將大檔案分成小部分,分片上傳,並事實的記錄上傳的進度,保證上傳中斷後,再次上傳時還是從上一次中斷的地方開始的;
下面就直接貼上我的demo程式碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>大檔案上傳</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script> </head> <body> <div class="file-upload-box"> <input id="file-input" type="file"> <button onclick="stopup()" id="stop">上傳</button> </div> <progress value="0" max="10" id="prouploadfile" style="width:300px;"></progress> <span id="persent">0%</span> <script type="text/javascript"> let fileInput=document.getElementById("file-input"); let stopbutton = document.getElementById('stop'); //上傳進度 let pro = document.getElementById('prouploadfile'); let persent = document.getElementById('persent'); fileInput.addEventListener("change",function(e){ //獲取檔案物件 let fileList = e.target.files; resultfile = fileList[0]; //切片計算 filesize= resultfile.size;//上傳檔案大小 setsize=1000*1024;//定義切片大小 filecount = filesize/setsize;//計算切片數量 //定義進度條 pro.max=parseInt(Math.ceil(filecount)); i =getCookie(resultfile.name); i = (i!==null && i!=="")?parseInt(i):0; if(Math.floor(filecount)<i){ alert("該檔案已經上傳完成,請勿重複上傳!"); pro.value=i+1; persent.innerHTML="100%"; }else{ pro.value=i; p=parseInt(i)*100/Math.ceil(filecount); persent.innerHTML=parseInt(p)+"%"; } },false); //3.ajax上傳 let stop=1; function xhr2(){ if(stop===1){ return false; } if(resultfile===""){ alert("請選擇檔案!"); return false; } i=getCookie(resultfile.name); i = (i!=null && i!=="")?parseInt(i):0; if(Math.floor(filecount)<parseInt(i)){ alert("已經上傳完成!"); return false; } let xhr = new XMLHttpRequest();//第一步 //新建一個FormData物件 let formData = new FormData(); //追加檔案資料 //改變進度條 pro.value=i+1; p=parseInt(i+1)*100/Math.ceil(filecount); persent.innerHTML=parseInt(p)+"%"; //進度條 if((filesize-i*setsize)>setsize){ blobfile= resultfile.slice(i*setsize,(i+1)*setsize); }else{ blobfile= resultfile.slice(i*setsize,filesize); formData.append('lastone', Math.floor(filecount)); } formData.append('file', blobfile); formData.append('blobname', i); formData.append('filename', resultfile.name); //設定響應返回的資料格式 //post方式 xhr.open('POST', 'http://127.0.0.1:8081/largeFileUpload/data/fileSave.php'); //第二步驟 //傳送請求 xhr.send(formData); //第三步驟 stopbutton.innerHTML = "暫停"; //ajax返回 xhr.onreadystatechange = function(){ //第四步 if ( xhr.readyState === 4 && xhr.status === 200 ) { //請求成功 //console.log(xhr.responseText); if(i<filecount){ xhr2(); }else{ i=0; alert("上傳完成!"); window.location.reload(); } if(xhr.responseText!=="not end"){ window.parent.$('#affixdiv').after(xhr.responseText); }else{ console.log('正在分片上傳中('+Math.floor(filecount)+')...'+i); } } }; //設定超時時間 xhr.timeout = 20000; xhr.ontimeout = function(event){ alert('請求超時,網路擁堵!\n(如果檔案已經上傳完成,請忽略此訊息!)'); }; i=i+1; setCookie(resultfile.name,i,1);//Cookie有效時間1天 } //設定cookie function setCookie(c_name,value,expiredays) { let exdate=new Date(); exdate.setDate(exdate.getDate()+expiredays); document.cookie=c_name+ "=" +escape(value)+((expiredays==null) ? "" : ";expires="+exdate.toGMTString()+";path=/"); } //獲取cookie function getCookie(c_name) { if (document.cookie.length>0) { c_start=document.cookie.indexOf(c_name + "="); if (c_start!==-1) { c_start=c_start + c_name.length+1; c_end=document.cookie.indexOf(";",c_start); if (c_end===-1) c_end=document.cookie.length; return unescape(document.cookie.substring(c_start,c_end)); } } return ""; } function stopup(){ if(stop===1){ stop = 0; xhr2(); }else{ stop = 1; stopbutton.innerHTML = "繼續"; } } </script> </body> </html>
在使用的時候需要將上傳地址更改為自己的後臺地址即可;