1. 程式人生 > >網頁內實現大檔案分片上傳、斷點續傳

網頁內實現大檔案分片上傳、斷點續傳

最近做公司的專案,需要在後臺控制系統中新增一個功能-------向伺服器傳送程式更新包;這些程式更新包大小不固定,但基本都在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>

在使用的時候需要將上傳地址更改為自己的後臺地址即可;