当前位置:文档之家› php+html5实现无刷新上传、大文件分片上传、断点续传的方法

php+html5实现无刷新上传、大文件分片上传、断点续传的方法

php+html5实现无刷新上传、大文件分片上传、断点续传的方法理清思路:引入了两个概念:块(block)和片(chunk)。

每个块由一到多个片组成,而一个资源则由一到多个块组成。

块是服务端的永久数据存储单位,片则只在分片上传过程中作为临时存储的单位。

服务端会以约一个月为单位周期性的清除上传后未被合并为块的数据片。

实现过程:将文件分割,分片上传,然后合并。

前端代码:<!doctype html><html><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width,user-scalable=no,initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0"><meta http-equiv="X-UA-Compatible"content="ie=edge"><title>Document</title><style>#progress{width:300px;height:20px;background-color:#f7f7f7;box-shadow:inset01px2px rgba(0,0,0,0.1);border-radius:4px;background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);}#finish{background-color:#149bdf;background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent25%,transparent50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15)75%,transparent75%,transparent); background-size:40px40px;display:inline-block;height:20px;}form{margin-top:50px;}</style></head><body><p id="progress"><span id="finish"style="width:0%;"progress="0"></span></p><form action=""><input type="file"name="file"id="file"><input type="button"value="停止"id="stop"> </form><script>var fileForm=document.getElementById("file"); var stopBtn=document.getElementById('stop'); var upload=new Upload();fileForm.onchange=function(){upload.addFileAndSend(this);}stopBtn.onclick=function(){this.value="停止中";upload.stop();this.value="已停止";}function Upload(){var xhr=new XMLHttpRequest();var form_data=new FormData();const LENGTH=1024*1024;var start=0;var end=start+LENGTH;var blob;var blob_num=1;var is_stop=0//对外方法,传入文件对象this.addFileAndSend=function(that){ var file=that.files[0];blob=cutFile(file);sendFile(blob,file);blob_num+=1;}//停止文件上传this.stop=function(){xhr.abort();is_stop=1;}//切割文件function cutFile(file){var file_blob=file.slice(start,end); start=end;end=start+LENGTH;return file_blob;};//发送文件function sendFile(blob,file){var form_data=new FormData();var total_blob_num=Math.ceil(file.size/LENGTH);form_data.append('file',blob);form_data.append('blob_num',blob_num);form_data.append('total_blob_num',total_blob_num);form_data.append('file_name',);xhr.open('POST','./statics/style/index.php',false);xhr.onreadystatechange=function(){if(xhr.readyState==4&&xhr.status==200){console.log(xhr.responseText);}var progress;var progressObj=document.getElementById('finish');if(total_blob_num==1){progress='100%';}else{progress=Math.min(100,(blob_num/total_blob_num)*100)+'%'; console.log(progress);console.log('分割');}progressObj.style.width=progress; var t=setTimeout(function(){if(start<file.size&&is_stop===0){ blob=cutFile(file);sendFile(blob,file);blob_num+=1;}else{setTimeout(t);}},1000);}xhr.send(form_data);}}</script></body></html>后台PHP代码:<?phpclass Upload{private$filepath='./upload';//上传目录private$tmpPath;//PHP文件临时目录private$blobNum;//第几个文件块private$totalBlobNum;//文件块总数private$fileName;//文件名Public function __construct($tmpPath,$blobNum,$totalBlobNum,$fileName){$this->tmpPath=$tmpPath;$this->blobNum=$blobNum;$this->totalBlobNum=$totalBlobNum;//文件名编码$this->fileName=iconv('utf-8','gbk',$fileName);$this->moveFile();$this->fileMerge();}//判断是否是最后一块,如果是则进行文件合成并且删除文件块private function fileMerge(){if($this->blobNum==$this->totalBlobNum){$blob='';for($i=1;$i<=$this->totalBlobNum;$i++){$blob=file_get_contents($this->filepath.'/'.$this->fileName.'__'.$i);file_put_contents($this->filepath.'/'.$this->fileName,$blob,FILE_APPEND);}$this->deleteFileBlob();}}//删除文件块private function deleteFileBlob(){for($i=1;$i<=$this->totalBlobNum;$i++){@unlink($this->filepath.'/'.$this->fileName.'__'.$i);}}//移动文件private function moveFile(){$this->touchDir();$filename=$this->filepath.'/'.$this->fileName.'__'.$this->blobNum; move_uploaded_file($this->tmpPath,$filename);}//API返回数据public function apiReturn(){if($this->blobNum==$this->totalBlobNum){if(file_exists($this->filepath.'/'.$this->fileName)){$data['code']=2;$data['msg']='success';$data['file_path']= 'http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_FILENAME'] ).str_replace('.','',$this->filepath).'/'.$this->fileName;$data['blobNum']=$this->blobNum;$data['totalBlobNum']=$this->totalBlobNum;}}else{if(file_exists($this->filepath.'/'.$this->fileName.'__'.$this->blobNum)){ $data['code']=1;$data['msg']='waiting for all';$data['file_path']='';$data['blobNum']=$this->blobNum;$data['totalBlobNum']=$this->totalBlobNum;}}header('Content-type:application/json');echo json_encode($data);}//建立上传文件夹private function touchDir(){if(!file_exists($this->filepath)){return mkdir($this->filepath);}}}if(!isset($_POST['blob_num'])){exit("error");}//实例化并获取系统变量传参$upload=new Upload($_FILES['file']['tmp_name'],$_POST['blob_num'],$_POST['total_blo b_num'],$_POST['file_name']);//调用方法,返回结果$upload->apiReturn();?>亲测有效,有兴趣的同学可以自己动手实践下。

相关主题