铁东博客

PHP怎么样去解决上传大文件

在开发网站系统的时候,经常会使用到文件上传的功能,一般都会限制文件上传的大小,当突然遇到一个大文件要上传的时候,业务就会提需求要把上传的文件修改大,在php中默认的上传文件的大小是有限制的,默认是2M,如果你要上传大文件,就需要修改php.ini文件的配置,如下几个参数:

    upload_max_filesize = 2M //PHP最大能接受的文件大小
    post_max_size = 8M //PHP能收到的最大POST值'
    memory_limit = 128M //内存上限
    max_execution_time = 30 //最大执行时间

当文件上升到GB级别的时候,简单粗暴的把上面几个值调大,但是你的服务器的内存也会被耗尽,这种粗暴的方式迟早会出现问题
解决方式,当然是切割文件上传,HTML5开放了新的FILE API也可以直接操作二进制对象,我们可以直接在浏览器端实现文件切割

测试代码

这个代码是网上找的

css代码:

  #progress{
   width: 300px;
   height: 20px;
   background-color:#f7f7f7;
   box-shadow:inset 0 1px 2px 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%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);
   background-size:40px 40px;
   height: 100%;
  }
  form{
   margin-top: 50px;
  }

html代码:

js代码:

 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 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',file.name);
 
   xhr.open('POST','./upload.php',false);
   xhr.onreadystatechange = function () {
    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 ) +'%';
    }
    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);
  }
 }



PHP上传文件:

class 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 = $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);
  $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['DOCUMENT_URI']).str_replace('.','',$this->filepath).'/'. $this->fileName;
   }
 }else{
   if(file_exists($this->filepath.'/'. $this->fileName.'__'.$this->blobNum)){
    $data['code'] = 1;
    $data['msg'] = 'waiting for all';
    $data['file_path'] = '';
   }
 }
 header('Content-type: application/json');
 echo json_encode($data);
}
 
//建立上传文件夹
private function touchDir(){
 if(!file_exists($this->filepath)){
  return mkdir($this->filepath);
 }
}
}

//实例化并获取系统变量传参
$upload = new Upload($_FILES['file']['tmp_name'],$_POST['blob_num'],$_POST['total_blob_num'],$_POST['file_name']);
//调用方法,返回结果
$upload->apiReturn();


未经允许不得转载:铁东博客 » PHP怎么样去解决上传大文件

评论,共有 0 条评论

  • 昵称 (必填)
  • 邮箱 (必填)
暂无评论数据,赶紧来评论吧