网页内实现大文件分片上传、断点续传
程序员文章站
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>
在使用的时候需要将上传地址更改为自己的后台地址即可;