Maison  >  Article  >  développement back-end  >  js+php télécharge des fichiers volumineux en plusieurs parties

js+php télécharge des fichiers volumineux en plusieurs parties

不言
不言original
2018-04-18 15:08:225391parcourir

Le contenu de cet article concerne le téléchargement en plusieurs parties js+php de fichiers volumineux. Il a une certaine valeur de référence. Maintenant, je le partage avec tout le monde. Les amis dans le besoin peuvent s'y référer

1. part


Pourquoi le serveur ne peut-il pas transférer directement des fichiers volumineux ? C'est lié à plusieurs configurations dans php.ini

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

Bien entendu, vous ne pouvez pas augmenter simplement et grossièrement les valeurs ci-dessus, sinon ce ne sera qu'une question de temps avant que les ressources mémoire du serveur ne soient épuisées.

Solution

Heureusement, HTML5 a ouvert une nouvelle API FILE, qui peut également faire fonctionner directement des objets binaires. Nous pouvons directement implémenter la découpe de fichiers côté navigateur. Selon la pratique précédente, nous avons. utiliser Flash La solution sera très difficile à mettre en œuvre.

Idée JS
1. Écoutez l'événement onchange du bouton de téléchargement
2 Récupérez l'objet FILE du fichier
3. Coupez l'objet FILE du fichier et joignez-le. l'objet FORMDATA
4. Envoyez l'objet FORMDATA au serveur via AJAX
5. Répétez les étapes 3 et 4 jusqu'à ce que le fichier soit envoyé.

Idées PHP
1. Créez un dossier de téléchargement
2 Déplacez les fichiers du répertoire temporaire de téléchargement vers le dossier de téléchargement
3. Une fois tous les blocs de fichiers téléchargés, effectuez la synthèse des fichiers4. Supprimez le dossier
5. Revenez au chemin du fichier téléchargé



2.html partie

<!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>
Partie 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();
3. Problèmes avec la configuration de php.ini rencontrés lors du débogage

3.1

      post_max_size = 10M:
3.2

max_file_uploads : 20

3.3

memory_limit:128M;(解释:php页面消耗的最大内存)


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn