2012-05-24 68 views
5

使用HTML5分块,我可以用小块文件上传文件。但是,当它开始使用多个http POST请求时会出现问题,这会导致计算机变慢或可能崩溃。如果我有5个文件,它将只有5个http请求eventhough我使用html5分割块如何在1个http请求下上载多个文件

例如:如果我上传5个文件,每个文件将被拆分到1mb块,所以如果第一个文件是10MB,那么它将变成10块1mb块。问题是,每个块将在1个http请求下,因此只有第一个文件将是10个HTTP请求。 想象一下,如果我有1GB的文件,它会变成1000 HTTP请求,并放慢计算机。

这是示例代码:

 //Prepare element progress after the page load completely 
     var uploaders = []; 
     var totalChunks = 0; 
     var progress; 
     var bars; 
     $(document).ready(function() { 
      //progress = document.querySelector('progress'); 
      //bars = document.querySelector('#bars'); 
     });   

     //function for after the button is clicked, slice the file 
     //and call upload function 
     function sendRequest() {  
      //clean the screen 
      //bars.innerHTML = ''; 


      var file = document.getElementById('fileToUpload'); 

      for(var i = 0; i < file.files.length; i++) {  
       var blob = file.files[i];   
       var originalFileName = blob.name; 
       var filePart = 0 

       const BYTES_PER_CHUNK = 10 * 1024 * 1024; // 10MB chunk sizes. 
       const SIZE = blob.size; 

       var start = 0; 
       var end = BYTES_PER_CHUNK; 

       totalChunks = Math.ceil(SIZE/BYTES_PER_CHUNK); 

       while(start < SIZE) {      
        if (blob.webkitSlice) { 
         //for Google Chrome 
         var chunk = blob.webkitSlice(start, end); 
        } else if (blob.mozSlice) { 
         //for Mozilla Firefox 
         var chunk = blob.mozSlice(start, end); 
        }  

        uploadFile(chunk, originalFileName, filePart, totalChunks, i); 
        filePart++; 
        start = end; 
        end = start + BYTES_PER_CHUNK; 
       } 
      }     
     } 

     function uploadFile(blobFile, fileName) { 
      var fd = new FormData(); 
      fd.append("fileToUpload", blobFile); 

      var xm = $.ajax({ 
       url: "upload.php"+"?"+"file1="+fileName, 
       type: "POST", 
       data: fd, 
       processData: false, 
       contentType: false, 
      });    
     } 

     function uploadFile(blobFile, fileName, filePart, totalChunks, divBarsSelector) { 
      if(filePart == 0) { 
       bars = document.querySelector('#bars' + divBarsSelector); 
      } 

      var progress = document.createElement('progress'); 
      progress.min = 0; 
      progress.max = 100; 
      progress.value = 0; 
      bars.appendChild(progress); 

      var fd = new FormData(); 
      fd.append("fileToUpload", blobFile); 

      var xhr = new XMLHttpRequest();     
      xhr.open("POST", "upload.php"+"?"+"file="+fileName + filePart, true); 

      xhr.onload = function(e) { 
       //make sure if finish progress bar at 100% 
       progress.value = 100; 

       //counter if everything is done using stack 
       uploaders.pop(); 

       if (!uploaders.length) { 
        bars.appendChild(document.createElement('br')); 
        bars.appendChild(document.createTextNode('DONE :)')); 
        //mergeFile(fileName, totalChunks); 
       }     
      }; 

      // Listen to the upload progress for each upload. 
      xhr.upload.onprogress = function(e) {; 
       if (e.lengthComputable) { 
        progress.value = (e.loaded/e.total) * 100; 
       } 
      };     

      uploaders.push(xhr); 
      xhr.send(fd); 
     } 

和用于接收的服务器部分将是upload.php的

$target_path = "uploads/"; 
$tmp_name = $_FILES['fileToUpload']['tmp_name']; 
$size = $_FILES['fileToUpload']['size']; 
$name = $_FILES['fileToUpload']['name']; 

$originalName = $_GET['file']; 

print_r("*******************************************\n"); 
print_r($originalName); 
print_r("\n"); 
print_r($_FILES); 
print_r("\n"); 
print_r("*******************************************\n"); 
$target_file = $target_path . basename($name); 

//Result File 
$complete = $originalName; 
$com = fopen("uploads/".$complete, "ab"); 
error_log($target_path); 

if ($com) { 
    // Read binary input stream and append it to temp file 
    $in = fopen($tmp_name, "rb"); 
    if ($in) { 
     while ($buff = fread($in, 1048576)) { 
      fwrite($com, $buff); 
     } 
    } 
    fclose($in); 
    fclose($com); 
} 
+0

如果你不希望你的文件分割成多个部分,那么你为什么要摆在首位分裂他们做? – Carsten

+0

不,我需要他们分手。因为1. PHP有上传限制(我知道我可以改变这个限制,但这不是一个真正的解决方案)2.这种方式我可以一次上传多个文件,这会使文件更快。 – Harts

+0

实际上分割文件也会帮我实现恢复文件(万一连接突然下来),用户不必从头再开始 – Harts

回答

6

在您的评论读你的动机后,我想指出一个很少有'误解'。首先,它是而不是建议分割一个文件,然后一次上传所有分割的部分。拆分文件起来的全部要点是绕过PHP上传限制(其中,如果适用,应该改变和可能是一个真正的解决方案*),而是通过做顺序不同的部分这允许客户端计算机的负载极小,特别是如果您正在考虑上传1GB内容。无论哪种方式,没有理由将文件拆分并接下来将其组合在一个请求中(尽管这在理论上可能与XMLHttpRequest2相同,但如果您可以使用XMLHttpRequest2,那么您不必担心无论以何种方式拆分文件,因为它提供了干净地上传多个文件的必要控件)。

*请注意,如果你这样做,你必须确保你的PHP内存设置是否正确设置(以防止PHP试图完全加载到内存中写入到一个临时文件之前,但是这不应该”在我认为的默认设置下,不会发生在最新版本的PHP上)。 (我觉得有必要补充一点,我没有使用PHP和PHP上传几年,所以我可能会误解最后的评论)

无论哪种方式,文件分块大约5-25MB(取决于你期望的连接有多好:P)+顺序上传(如果XMLHttpRequest2可用,加上一个很好的进度条,否则每个块有一个进度条)似乎是一个明智的方式,同时防止浏览器过载。 (哦,如果你需要支持老的浏览器,我会真的建议你看看闪存上传,因为尽管苹果说闪光是邪恶的,在大多数(过时的)电脑上它会给迄今为止最好的体验)

+0

实际上分割文件也会帮助我实现恢复文件(万一连接突然下了),用户不必从头再次开始。那么,根据您的解决方案,同时上传并不是一个好主意?我应该坚持按顺序上传?顺便说一句,Flash和Java不是一个选项,因为我试图摆脱这一点,这就是为什么我使用HTML5。谢谢 – Harts

+0

这不是一个选项“因为”你试图摆脱它?这不是我希望的原因,因为你不应该为了移动本身而转向HTML5(目前没有任何内容更好,因为它比闪存可用性支持更差)。无论如何,就恢复文件上传而言,这就是为什么我说在我的结论中拆分文件将是一个好主意,并且取决于连接质量使块尽可能大,但是如果您同时上传它们,则会失去所有优点。 (因为恢复上传也是不现实的) –

+0

不,我的意思是我已经使用Java编写的项目(和工作),现在我试图在HTML5中重写它以备将来使用。我知道目前HTML5仍然不如java或flash – Harts

1

Java上传器[即JumpLoader] - 我不是说“使用它们”,而是学习它们是如何工作的。到目前为止,我所见过的最好的上传实践是:1)将文件拆分成一定大小的块,2)顺序地上传块(另外通过提供块的散列,如果数据敏感),3)在服务器端联合块但如果您正在使用它们,则通过散列验证数据完整性)。

因此,您将绕过PHP的max_upload_size限制。否则,我个人并不认为为什么有人应该将数据拆分成大块。

0

试试这个:

<script type="text/javascript"> 
    //Prepare element progress after the page load completely 
    var uploaders = []; 
    var totalChunks = 0; 
    var progress; 
    var bars; 
    $ (document).ready(function() { 
     //progress = document.querySelector('progress'); 
     //bars = document.querySelector('#bars'); 
    });   

    //function for after the button is clicked, slice the file 
    //and call upload function 
    function sendRequest() { 
     //clean the screen 
     //bars.innerHTML = ''; 

     var file = document.getElementById('fileToUpload'); 

     for(var i = 0; i < file.files.length; i++) { 
      var blob = file.files[i]; 
      var originalFileName = blob.name; 
      var filePart = 0 

      const BYTES_PER_CHUNK = 10 * 1024 * 1024; // 10MB chunk sizes. 
      const SIZE = blob.size; 

      var start = 0; 
      var end = BYTES_PER_CHUNK; 

      totalChunks = Math.ceil(SIZE/BYTES_PER_CHUNK); 

      while(start < SIZE) { 
       if (blob.webkitSlice) { 
        //for Google Chrome 
        var chunk = blob.webkitSlice(start, end); 
       } else if (blob.mozSlice) { 
        //for Mozilla Firefox 
        var chunk = blob.mozSlice(start, end); 
       }  

       uploadFile(chunk, originalFileName, filePart, totalChunks, i); 
       filePart++; 
       start = end; 
       end = start + BYTES_PER_CHUNK; 
      } 
     } 
    } 

    function uploadFile(blobFile, fileName) { 
     var fd = new FormData(); 
     fd.append("fileToUpload", blobFile); 

     var xm = $ .ajax({ 
      url: "upload.php"+"?"+"file1="+fileName, 
      type: "POST", 
      data: fd, 
      processData: false, 
      contentType: false, 
     }); 
    } 

    function uploadFile(blobFile, fileName, filePart, totalChunks, divBarsSelector) { 
     if(filePart == 0) { 
      bars = document.querySelector('#bars' + divBarsSelector); 
     } 

     var progress = document.createElement('progress'); 
     progress.min = 0; 
     progress.max = 100; 
     progress.value = 0; 
     bars.appendChild(progress); 

     var fd = new FormData(); 
     fd.append("fileToUpload", blobFile); 

     var xhr = new XMLHttpRequest(); 
     xhr.open("POST", "upload.php"+"?"+"file="+fileName + filePart, true); 

     xhr.onload = function(e) { 
      //make sure if finish progress bar at 100% 
      progress.value = 100; 

      //counter if everything is done using stack 
      uploaders.pop(); 

      if (!uploaders.length) { 
       bars.appendChild(document.createElement('br')); 
       bars.appendChild(document.createTextNode('DONE :) ')); 
       //mergeFile(fileName, totalChunks); 
      } 
     }; 

     // Listen to the upload progress for each upload. 
     xhr.upload.onprogress = function(e) {; 
      if (e.lengthComputable) { 
       progress.value = (e.loaded/e.total) * 100; 
      } 
     };     

     uploaders.push(xhr); 
     xhr.send(fd); 
    } 
</script> 
+0

我的代码有什么不同?我似乎无法找到差异? – Harts