大文件上传

index.html

<!DOCTYPE html>
<html>
<head>
	<title>大文件上传</title>
	<meta charset="utf-8">
	<link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui/css/layui.css" />
</head>
<body>

	<div>
		
		<fieldset class="layui-elem-field layui-field-title" style="margin-top: 30px;">
		  <legend>大文件上传</legend>
		</fieldset> 
		 
		<input type="file" name="file" id="file_demo">

		<div class="layui-upload-list">
			<img  id="demo1">
			<p id="demoText"></p>
		</div>

		<fieldset class="layui-elem-field layui-field-title" style="margin-top: 50px;">
		  <legend>上传进度</legend>
		</fieldset>
		 
		<div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="demo">
		  <div class="layui-progress-bar layui-bg-red" lay-percent="0%"></div>
		</div>

		<button type="button" class="layui-btn" style="margin-top: 50px;" lay-active="begin">开始上传</button>


	</div>

</body>
<script type="text/javascript" src="https://www.layuicdn.com/layui-v2.5.4/layui.js"></script>
<script type="text/javascript">
	var BYTES_PER_SLICE = 2<<18;
	console.log(BYTES_PER_SLICE);
	layui.use(['element','util','layer'],function(){
		var $ = layui.$
			,element = layui.element
			,util = layui.util
			,layer = layui.layer
			,BYTES_PER_SLICE = 2<<18			//  切片大小
			,hasSendNum = 0					//  以发送数量
			,totalSlices					//  总切片数
			,file,totalSize;
		util.event('lay-active',{

			begin: function() {
					//  文件
					file = $('#file_demo')[0].files[0]
					if(file==undefined){
						alert("文件为空")
						window.location.reload()
					}
					// 文件的总字节数
        			totalSize = file.size
        			// 当前切片数
        		var index = 0
        			// 切片的开始和结束
        			,start,end
        			// 上传文件名
        			,fileName = file.name;
        		//  初始化以发送数量
        		hasSendNum = 0;
        		//  总切片数
        		totalSlices = Math.ceil(totalSize/BYTES_PER_SLICE);

        		checkFile(fileName)
        		
        		//uploadSliceFile(index, fileName);

			}
		},'click')

	function checkFile(fileName){
		$.ajax({
			url: './checkFile.php'
			,data: {"file":fileName}
			,type: 'post'
			,async: false
        	,success: function(obj){
        		var arr = JSON.parse(obj)
				console.log(arr)
        		if(arr.page>1){
					uploadSliceFile(arr.page,fileName)
				}else{
					uploadSliceFile(arr.page,fileName)
				}
			}
        	
		})
	}

	function uploadSliceFile(page, filename){
		//  切片开始位置
		start = page * BYTES_PER_SLICE;
		//  切片结束位置
		end = start + BYTES_PER_SLICE
		//  切割文件
		var slice = file.slice(start,end);
        console.log("----------")
        console.log(start)
        console.log(end)
        console.log(filename)
		var Data = new FormData();
		Data.append('file', slice);
		Data.append('page', page);
		Data.append('filename', filename);
		Data.append('pages', totalSlices)

		$.ajax({
			url: './index.php'
			,data: Data
			,type: 'post'
			,dataType: 'json'
			,processData : false // 使数据不做处理
        	,contentType : false // 不要设置Content-Type请求头
        	,async: true
        	,success: function(obj){
        			var progress = (((page + 1)/totalSlices) * 100).toFixed(2)

        			element.progress('demo',obj.code == 1 ? '100%' : progress+'%');

        			if(page + 1 < totalSlices){

        				uploadSliceFile(++page, filename);
        			}

        	}
        	,error: function(response){
        		// 失败时 重新上传
        		 return false
        	}
		})


	}

	})
</script>
</html>

index.php:



$post = !empty($_POST) ? $_POST : '';

$file = !empty($_FILES['file'])  ? $_FILES['file'] : '';

if(!$post || !$file){

    echo json_encode(['code' => 1001, 'msg' => 'error', 'data' => []]);exit;
}

$uploadSliceFile = new uploadSliceFile($post['filename'], $post['page'], $post['pages'], $file['tmp_name']);

$uploadSliceFile ->apiReturn();




class uploadSliceFile{

    private $filename;                              // 文件名

    private $filepath = "../file/uploads/";         // 分片上传目录

    private $filespath = '../file/upload/';         // 文件上传目录

    private $sliceNum;                              // 分块数(第几页

    private $tmpPath;                               // 上传文件临时目录

    private $totalBlobNum;                          // 总块数(总页数)

    public function __construct($filename, $sliceNum, $totalBlobNum, $tmpPath){

        $this ->filename = $filename;
        
        $this ->sliceNum = $sliceNum;

        $this ->totalBlobNum = $totalBlobNum;

        $this ->tmpPath = $tmpPath;

        $this ->filepath .= md5($this ->filename);

        $this ->moveFile();

        $this ->fileMerge();
    }





    //API返回数据
    public function apiReturn(){
        if($this->sliceNum == $this->totalBlobNum - 1){
 
            if(file_exists($this->filespath.'/'. $this->filename)){
 
                $data['code'] = 1;
 
                $data['msg'] = 'success';
 
                $data['file_path'] = $this->filespath.'/'. $this->filename;
 
            }
 
        }else{
 
            if(file_exists($this->filepath.'/'. $this->filename.'_'.$this->sliceNum)){
 
                $data['code'] = -1;
 
                $data['msg'] = 'waiting';
 
                $data['file_path'] = '';
 
            }
 
        }
 
        // header('Content-type: application/json');
 
        echo json_encode($data);
 
    }

    //移动文件
    private function moveFile(){

        $this->touchDir();
 
        $filename = $this->filepath.'/'. $this->filename.'_'.$this->sliceNum;

        move_uploaded_file($this->tmpPath,$filename);

    }

    //建立上传文件夹
    private function touchDir(){
 
        if(!file_exists($this->filepath)){
 
            return mkdir($this->filepath);
 
        }
 
    }

    //判断是否是最后一块,如果是则进行文件合成并且删除文件块
    private function fileMerge(){
 
        if($this->sliceNum == $this->totalBlobNum - 1){
 
            $blob = '';
 
            for($i = 0; $i < $this->totalBlobNum; $i++){
 
                $blob = file_get_contents($this->filepath.'/'. $this->filename.'_'.$i);
                if(!file_exists($this->filespath)){
                    mkdir($this->filepath,775,true);
                }
                file_put_contents($this->filespath.'/'. $this->filename,$blob,FILE_APPEND);
 
            }

            $this->deleteFileBlob();
        }
    }

    //删除文件块
    private function deleteFileBlob(){
 
        for($i = 0; $i < $this->totalBlobNum; $i++){
 
            unlink($this->filepath.'/'. $this->filename.'_'.$i);
            @rmdir($this->filepath);
 
        }
 
    }
}

checkFile.php


$post = !empty($_POST['file']) ? $_POST : '';
$checkFile = new checkFile($post['file']);

class checkFile{
    private $filename;                              // 文件名
    private $filepath = "../file/uploads/";         // 分片上传目录

    public function __construct($filename){
      $this ->filename = $filename;
      $this ->filepath .= md5($this ->filename);
//        mkdir($this ->filepath,755,true);
      $this ->checkDir();  
    }

    public function checkDir(){
        if(file_exists($this ->filepath)){
            $i = 0;
            while ($i<(2<<15)) {
                if(!file_exists($filename = $this->filepath.'/'. $this->filename.'_'.$i)&&$i>0){
                    $data['code'] = 3;

                    $data['msg'] = 'success';
     
                    $data['page'] = $i;
                    echo json_encode($data);break;
                }
                $i++;
            }
         }else{

         			$data['code'] = -3;
 
                    $data['msg'] = 'success';
     
                    $data['page'] = 0;

                    echo json_encode($data);
         }

    }


}

你可能感兴趣的:(大文件上传,切片)