PHP文件上传进度:文件切片上传

设置文件上传大小限制,修改如下:
upload_max_filesize = 50m; 允许上传文件大小的最大值。默认为2M
post_max_size = 50m; 指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值。默认为8M
max_execution_time = 600; 每个PHP页面运行的最大时间值(秒),默认30秒
max_input_time = 600; 每个PHP页面接收数据所需的最大时间,默认60秒
memory_limit = 128m; 每个PHP页面所吃掉的最大内存,默认8M
 

<!doctype html>
<html lang="en">

<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: 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;
        }
    </style>
</head>

<body>
    <div id="progress">
        <div id="finish" style="width: 0%;" progress="0"></div>
    </div>
    <form action="./upload.php">
        <input type="file" name="file" id="file">
    </form>
    <script>
        var fileForm = document.getElementById("file");
        var stopBtn = document.getElementById('stop');
        var upload = new Upload();

        fileForm.onchange = function () {
            upload.addFileAndSend(this);
        }

        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) {
                console.log("发送文件");
                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 (res) {
                    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;

                    if(xhr.readyState != 4){ return; }
                    // if( JSON.parse(res.target.responseText).code==1){ alert("文件上传成功!"); return;}
                    console.log("返回文本:",xhr.readyState, xhr.status, res.target.responseText);
                    // console.log(JSON.parse(res.target.responseText));

                    var t = setTimeout(function () {
                        console.log("检查文件上传进度");
                        if (start < file.size && is_stop === 0) {
                            blob = cutFile(file);
                            sendFile(blob, file);
                            blob_num += 1;
                        } else {
                            setTimeout(t);
                        }
                    }, 100);
                }
                xhr.send(form_data);
            }
        }

    </script>
</body>

</html>

 

 

<?php
ini_set("upload_max_filesize", "20M");

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'] = 1;
          $data['msg'] = '文件上传成功';
          $data['file_path'] = '/sss/'.str_replace('.','',$this->filepath).'/'. $this->fileName;
        }
    }else{
        if(file_exists($this->filepath.'/'. $this->fileName.'__'.$this->blobNum)){
          $data['code'] = 0;
          $data['msg'] = '继续上传文件片段';
          $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();

 

代码来源忘记了,代码稍作改

修改时间 2019-06-25

真诚赞赏,手留余香
赞赏
随机推荐
我眼中的前端框架jQuery,Angular,React,Vue——以及我看前端架构
MySQL tag设计中,where in参数为带逗号的字符串查询
MySQL中UNION和UNION ALL的使用
MySQL汉字转换为拼音
Git 重写历史,修改commit 的注释
Nginx location 匹配顺序
2018.1.26 Night King
物理对齐和视觉对齐
PHP 富文本防止 XXS 攻击的方法
Node.js 如何使用 ES6 的模块功能
QQ号

微信联系我

夜间模式切换
回到顶部