>  기사  >  백엔드 개발  >  js+php 대용량 파일을 부분적으로 업로드

js+php 대용량 파일을 부분적으로 업로드

不言
不言원래의
2018-04-18 15:08:225432검색

이 글의 내용은 js+php 슬라이스로 대용량 파일을 업로드하는 내용입니다. 이제 모든 사람과 공유합니다. 도움이 필요한 친구들이 참고할 수 있습니다

1. 이유를 이해하세요. 서버에서 대용량 파일을 직접 전송할 수는 없나요? php.ini

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

의 여러 구성과 관련이 있습니다. 물론 위의 값을 간단하고 무례하게 늘릴 수는 없습니다. 그렇지 않으면 서버 메모리 리소스가 고갈되는 것은 시간 문제입니다.

솔루션 아이디어

다행히 HTML5에서는 바이너리 객체를 직접 조작할 수도 있는 새로운 FILE API를 열었습니다. 이전 사례에 따르면 Flash 솔루션을 사용해야 합니다. 구현하는데 많은 어려움이 있을 것입니다.

JS 아이디어

1. 업로드 버튼의 onchange 이벤트를 수신합니다.

2. 파일의 FILE 객체를 가져옵니다.

3. 파일의 FILE 객체를 잘라서 FORMDATA 객체에 첨부합니다. AJAX

를 통해 서버에 5. 파일이 전송될 때까지 3~4단계를 반복합니다.


PHP 아이디어
1. 업로드 폴더 만들기
2. 업로드 임시 디렉터리에서 파일을 업로드 폴더로 이동합니다
3. 모든 파일 블록이 업로드된 후 파일 합성을 수행합니다
4. 업로드로 돌아갑니다. 파일 경로 h 2.html 이후 일부

<!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: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>
<p id="progress">
    <p id="finish" style="width: 0%;" progress="0"></p>
</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(&#39;stop&#39;);
    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(&#39;file&#39;,blob);
            form_data.append(&#39;blob_num&#39;,blob_num);
            form_data.append(&#39;total_blob_num&#39;,total_blob_num);
            form_data.append(&#39;file_name&#39;,file.name);


            xhr.open(&#39;POST&#39;,&#39;http://www.test3.com/fenpian/upload.php&#39;,false);
            xhr.onreadystatechange  = function () {
     if (xhr.readyState==4 && xhr.status==200)
 {
     console.log(xhr.responseText);
     console.log(5555555555);
 }
 
 
     var progress;
                var progressObj = document.getElementById(&#39;finish&#39;);
                if(total_blob_num == 1){
                    progress = &#39;100%&#39;;
                }else{
                    progress = Math.min(100,(blob_num/total_blob_num)* 100 ) +&#39;%&#39;;
 console.log(progress);
 console.log(&#39;分割&#39;);
                }
                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>

3.php 부분

<?php
class Upload{
    private $filepath = &#39;./upload&#39;; //上传目录
    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 = &#39;&#39;;
            for($i=1; $i<= $this->totalBlobNum; $i++){
                $blob = file_get_contents($this->filepath.&#39;/&#39;. $this->fileName.&#39;__&#39;.$i);
				file_put_contents($this->filepath.&#39;/&#39;. $this->fileName,$blob,FILE_APPEND);
            }
            
           $this->deleteFileBlob();
        }
    }
    
   //删除文件块
    private function deleteFileBlob(){
        for($i=1; $i<= $this->totalBlobNum; $i++){
            @unlink($this->filepath.&#39;/&#39;. $this->fileName.&#39;__&#39;.$i);
        }
    }
    
    //移动文件
    private function moveFile(){
        $this->touchDir();
        $filename = $this->filepath.&#39;/&#39;. $this->fileName.&#39;__&#39;.$this->blobNum;
        move_uploaded_file($this->tmpPath,$filename);
    }
    
    //API返回数据
    public function apiReturn(){
        if($this->blobNum == $this->totalBlobNum){
                if(file_exists($this->filepath.&#39;/&#39;. $this->fileName)){
                    $data[&#39;code&#39;] = 2;
                    $data[&#39;msg&#39;] = &#39;success&#39;;
                    $data[&#39;file_path&#39;] = &#39;http://&#39;.$_SERVER[&#39;HTTP_HOST&#39;].dirname($_SERVER[&#39;DOCUMENT_URI&#39;]).str_replace(&#39;.&#39;,&#39;&#39;,$this->filepath).&#39;/&#39;. $this->fileName;
                }
        }else{
                if(file_exists($this->filepath.&#39;/&#39;. $this->fileName.&#39;__&#39;.$this->blobNum)){
                    $data[&#39;code&#39;] = 1;
                    $data[&#39;msg&#39;] = &#39;waiting for all&#39;;
                    $data[&#39;file_path&#39;] = &#39;&#39;;
                }
        }
        header(&#39;Content-type: application/json&#39;);
        echo json_encode($data);
    }
    
    //建立上传文件夹
    private function touchDir(){
        if(!file_exists($this->filepath)){
            return mkdir($this->filepath);
        }
    }
}


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


3.3


      post_max_size = 10M:


위 내용은 js+php 대용량 파일을 부분적으로 업로드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.