分片上传、断点续传

分片上传、断点续传

1、分片上传HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>分片上传</h2>
	<p>
		选择文件: <input type="file" id="file" name="file" />
	</p>
	<p>
		<input type="button" value="提交" onclick="commit()" />
	</p>
</body>
<script type="text/javascript">
//每个文件切片大小定为1M(1024*1024字节)(需要跟服务器协商好).
var BYTES_PER_SLICE = 1<<20;
// 已发送的数量
var  hasSendNum = 0;
// 总切片数
var totalSlices;

// 提交方法
function commit() {
    // 拿出选中的第一个文件
    var file = document.getElementById("file").files[0];
    // 文件的总字节数
    var totalSize = file.size;
    // 当前片数
    var index = 0;
    // 分片的开始、结束(不含)
    var start,end;
    // 文件名
    var fileName = file.name;
    // 初始化已发送数量为0
    hasSendNum = 0;

    // 计算文件切片总数(向上取整)
    totalSlices = Math.ceil(file.size / BYTES_PER_SLICE);
    // 不断循环将切片上传
    while(index < totalSlices) {
        start = index*BYTES_PER_SLICE;
        end = start + BYTES_PER_SLICE;

        var slice =file.slice(start,end);//切割文件
        uploadFile(slice, index++,fileName);
       
        console.log("size:",BYTES_PER_SLICE);
        console.log("num:",hasSendNum);
        console.log("slices:",totalSlices);
        console.log("start:",start) ;
        console.log("end:",end) ;
        console.log("index:",index) ;
        console.log("-------------");
    }
}

//上传文件
function uploadFile(slice, index,fileName) {
    var retry = 1;
    var formDate = new FormData();
    formDate.append("slice", slice);
    formDate.append("fileName",fileName);
    formDate.append("index",index);

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'sliceUpload', true);
    //false指同步上传,因为我的服务器内存较小,选择同步,如果追求速度,可以选择 //ture,异步上传
    xhr.onreadystatechange = ()=>uploadCallBack(xhr,slice,index,fileName);
    xhr.send(formDate);
}

/**
 * @desc 上传回调
 * @param xhr
 */
function uploadCallBack(xhr,slice,index,fileName) {
    if(xhr.readyState==4) {
        if(xhr.status==200) {
            if(xhr.responseText==1) {
                hasSendNum++;
                console.log("第"+index+"片,完成度"+parseInt(hasSendNum/totalSlices*100)+"%");
                if(hasSendNum==totalSlices) {
                    console.log("上传完毕");
                }
            }
        } else {
            console.log("上传失败,重试##################################");
            // 重试
            //uploadFile(slice, index,fileName);
        }
    }
}
</script>
</html>

2、后端代码

​
private final int BYTES_PER_SLICE = 1<<20;
    @RequestMapping(value="sliceUpload",method= RequestMethod.POST)
    @ResponseBody
    public int upload(@RequestParam("slice")MultipartFile slice,String fileName,int index) {
        int result = 0;
        if(slice.isEmpty()){
            return 0;
        }
        int size = (int) slice.getSize();
        System.out.println(fileName + "-->" + size);

        String path = "e:/test" ;
        File dest = new File(path + "/" + fileName);
        RandomAccessFile randomAccessFile = null;
        if(!dest.getParentFile().exists()){ //判断文件父目录是否存在
            dest.getParentFile().mkdir();
        }
        try {
            randomAccessFile = new RandomAccessFile(dest,"rw");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            byte[] bytes = slice.getBytes(); //保存文件
            randomAccessFile.seek(index*BYTES_PER_SLICE);
            randomAccessFile.write(bytes);
            result = 1;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                randomAccessFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

3、显示进度条,网速HTML(进度条是每个分片的,待调整)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>
    <span id="percentage"></span><span id="time"></span>
    <br /><br />
    <input type="file" id="file" name="myfile" />
    <input type="button" onclick="commit()" value="上传" />
    <input type="button" onclick="cancleUploadFile()" value="取消" />
</body>
<script type="text/javascript">
//每个文件切片大小定为1M(1024*1024字节)(需要跟服务器协商好).
var BYTES_PER_SLICE = 1<<20;

// 已发送的数量
var  hasSendNum = 0;

// 总切片数
var totalSlices;


// 提交方法
function commit() {
    // 拿出选中的第一个文件
    var file = document.getElementById("file").files[0];
    // 文件的总字节数
    var totalSize = file.size;
    // 当前片数
    var index = 0;
    // 分片的开始、结束(不含)
    var start,end;
    // 文件名
    var fileName = file.name;
    // 初始化已发送数量为0
    hasSendNum = 0;
    var ot;//
    var oloaded;

    // 计算文件切片总数(向上取整)
    totalSlices = Math.ceil(file.size / BYTES_PER_SLICE);
    // 不断循环将切片上传
    while(index < totalSlices) {
        start = index*BYTES_PER_SLICE;
        end = start + BYTES_PER_SLICE;

        var slice =file.slice(start,end);//切割文件
        uploadFile(slice, index++,fileName);
        
        console.log("size:",BYTES_PER_SLICE);
        console.log("num:",hasSendNum);
        console.log("slices:",totalSlices);
        console.log("start:",start) ;
        console.log("end:",end) ;
        console.log("index:",index) ;
        console.log("-------------");
    }
}

//上传文件
function uploadFile(slice, index,fileName) {
    var retry = 1;
    var formDate = new FormData();
    formDate.append("slice", slice);
    formDate.append("fileName",fileName);
    formDate.append("index",index);

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'sliceUpload', true);
    //false指同步上传,因为我的服务器内存较小,选择同步,如果追求速度,可以选择 //ture,异步上传
    //xhr.onload = uploadComplete; //请求完成
    //xhr.onerror =  uploadFailed; //请求失败
    xhr.onreadystatechange = ()=>uploadCallBack(xhr,slice,index,fileName);//上传回调
    xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
    xhr.upload.onloadstart = function(){//上传开始执行方法
        ot = new Date().getTime();   //设置上传开始时间
        oloaded = 0;//设置上传开始时,以上传的文件大小为0
    }; 
    xhr.send(formDate);
}

/**
 * @desc 上传回调
 * @param xhr
 */
function uploadCallBack(xhr,slice,index,fileName) {
    if(xhr.readyState==4) {
        if(xhr.status==200) {
            if(xhr.responseText==1) {
                hasSendNum++;
                console.log("第"+index+"片,完成度"+parseInt(hasSendNum/totalSlices*100)+"%");
                if(hasSendNum==totalSlices) {
                    console.log("上传完毕");
                }
            }
        } else {
            console.log("上传失败,重试##################################");
            // 重试
            //uploadFile(slice, index,fileName);
        }
    }
}
//上传进度实现方法,上传过程中会频繁调用该方法
function progressFunction(evt) {
     var progressBar = document.getElementById("progressBar");
     var percentageDiv = document.getElementById("percentage");
     // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
     if (evt.lengthComputable) {//
         progressBar.max = evt.total;
         progressBar.value = evt.loaded;
         percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
     }
    
    var time = document.getElementById("time");
    var nt = new Date().getTime();//获取当前时间
    var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差,单位为s
    ot = new Date().getTime(); //重新赋值时间,用于下次计算
    
    var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b       
    oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算

    //上传速度计算
    var speed = perload/pertime;//单位b/s
    var bspeed = speed;
    var units = 'b/s';//单位名称
    if(speed/1024>1){
        speed = speed/1024;
        units = 'k/s';
    }
    if(speed/1024>1){
        speed = speed/1024;
        units = 'M/s';
    }
    speed = speed.toFixed(1);
    //剩余时间
    var resttime = ((evt.total-evt.loaded)/bspeed).toFixed(1);
    time.innerHTML = ',速度:'+speed+units+',剩余时间:'+resttime+'s';
       if(bspeed==0)
        time.innerHTML = '上传已取消';
}
//上传成功响应
function uploadComplete(evt) {
 //服务断接收完文件返回的结果
 //    alert(evt.target.responseText);
     alert("上传成功!");
}
//上传失败
function uploadFailed(evt) {
    alert("上传失败!");
}
  //取消上传
function cancleUploadFile(){
    xhr.abort();
}
</script>
</html><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<progress id="progressBar" value="0" max="100" style="width: 300px;"></progress>
    <span id="percentage"></span><span id="time"></span>
    <br /><br />
    <input type="file" id="file" name="myfile" />
    <input type="button" onclick="commit()" value="上传" />
    <input type="button" onclick="cancleUploadFile()" value="取消" />
</body>
<script type="text/javascript">
//每个文件切片大小定为1M(1024*1024字节)(需要跟服务器协商好).
var BYTES_PER_SLICE = 1<<20;

// 已发送的数量
var  hasSendNum = 0;

// 总切片数
var totalSlices;


// 提交方法
function commit() {
    // 拿出选中的第一个文件
    var file = document.getElementById("file").files[0];
    // 文件的总字节数
    var totalSize = file.size;
    // 当前片数
    var index = 0;
    // 分片的开始、结束(不含)
    var start,end;
    // 文件名
    var fileName = file.name;
    // 初始化已发送数量为0
    hasSendNum = 0;
    var ot;//
    var oloaded;

    // 计算文件切片总数(向上取整)
    totalSlices = Math.ceil(file.size / BYTES_PER_SLICE);
    // 不断循环将切片上传
    while(index < totalSlices) {
        start = index*BYTES_PER_SLICE;
        end = start + BYTES_PER_SLICE;

        var slice =file.slice(start,end);//切割文件
        uploadFile(slice, index++,fileName);
        
        console.log("size:",BYTES_PER_SLICE);
        console.log("num:",hasSendNum);
        console.log("slices:",totalSlices);
        console.log("start:",start) ;
        console.log("end:",end) ;
        console.log("index:",index) ;
        console.log("-------------");
    }
}

//上传文件
function uploadFile(slice, index,fileName) {
    var retry = 1;
    var formDate = new FormData();
    formDate.append("slice", slice);
    formDate.append("fileName",fileName);
    formDate.append("index",index);

    var xhr = new XMLHttpRequest();
    xhr.open('POST', 'sliceUpload', true);
    //false指同步上传,因为我的服务器内存较小,选择同步,如果追求速度,可以选择 //ture,异步上传
    //xhr.onload = uploadComplete; //请求完成
    //xhr.onerror =  uploadFailed; //请求失败
    xhr.onreadystatechange = ()=>uploadCallBack(xhr,slice,index,fileName);//上传回调
    xhr.upload.onprogress = progressFunction;//【上传进度调用方法实现】
    xhr.upload.onloadstart = function(){//上传开始执行方法
        ot = new Date().getTime();   //设置上传开始时间
        oloaded = 0;//设置上传开始时,以上传的文件大小为0
    }; 
    xhr.send(formDate);
}

/**
 * @desc 上传回调
 * @param xhr
 */
function uploadCallBack(xhr,slice,index,fileName) {
    if(xhr.readyState==4) {
        if(xhr.status==200) {
            if(xhr.responseText==1) {
                hasSendNum++;
                console.log("第"+index+"片,完成度"+parseInt(hasSendNum/totalSlices*100)+"%");
                if(hasSendNum==totalSlices) {
                    console.log("上传完毕");
                }
            }
        } else {
            console.log("上传失败,重试##################################");
            // 重试
            //uploadFile(slice, index,fileName);
        }
    }
}
//上传进度实现方法,上传过程中会频繁调用该方法
function progressFunction(evt) {
     var progressBar = document.getElementById("progressBar");
     var percentageDiv = document.getElementById("percentage");
     // event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0
     if (evt.lengthComputable) {//
         progressBar.max = evt.total;
         progressBar.value = evt.loaded;
         percentageDiv.innerHTML = Math.round(evt.loaded / evt.total * 100) + "%";
     }
    
    var time = document.getElementById("time");
    var nt = new Date().getTime();//获取当前时间
    var pertime = (nt-ot)/1000; //计算出上次调用该方法时到现在的时间差,单位为s
    ot = new Date().getTime(); //重新赋值时间,用于下次计算
    
    var perload = evt.loaded - oloaded; //计算该分段上传的文件大小,单位b       
    oloaded = evt.loaded;//重新赋值已上传文件大小,用以下次计算

    //上传速度计算
    var speed = perload/pertime;//单位b/s
    var bspeed = speed;
    var units = 'b/s';//单位名称
    if(speed/1024>1){
        speed = speed/1024;
        units = 'k/s';
    }
    if(speed/1024>1){
        speed = speed/1024;
        units = 'M/s';
    }
    speed = speed.toFixed(1);
    //剩余时间
    var resttime = ((evt.total-evt.loaded)/bspeed).toFixed(1);
    time.innerHTML = ',速度:'+speed+units+',剩余时间:'+resttime+'s';
       if(bspeed==0)
        time.innerHTML = '上传已取消';
}
//上传成功响应
function uploadComplete(evt) {
 //服务断接收完文件返回的结果
 //    alert(evt.target.responseText);
     alert("上传成功!");
}
//上传失败
function uploadFailed(evt) {
    alert("上传失败!");
}
  //取消上传
function cancleUploadFile(){
    xhr.abort();
}
</script>
</html>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值