欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

网页内实现大文件分片上传、断点续传

程序员文章站 2024-02-19 11:19:10
...

最近做公司的项目,需要在后台控制系统中添加一个功能-------向服务器发送程序更新包;这些程序更新包大小不固定,但基本都在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>

在使用的时候需要将上传地址更改为自己的后台地址即可;