2012-05-24 68 views
5

Sử dụng tính năng chunk HTML5, tôi có thể tải tệp lên bằng phần nhỏ hơn. Nhưng vấn đề bắt đầu khi nó bắt đầu sử dụng nhiều yêu cầu http POST, điều này sẽ làm máy tính bị chậm lại hoặc có thể gặp sự cố. Có anyway để có các tập tin chia nhỏ theo một yêu cầu http .. vì vậy nếu tôi có 5 tập tin nó sẽ chỉ có 5 http yêu cầu eventhough tôi sử dụng html5 chia chunkCách tải lên nhiều tệp dưới 1 yêu cầu http

ví dụ: nếu tôi tải lên 5 tệp, mỗi tệp sẽ được chia đến 1mb chunk, vì vậy nếu tập tin đầu tiên là 10mb, sau đó nó sẽ trở thành 10 miếng của 1mb chunk. Và vấn đề là, mỗi đoạn sẽ dưới 1 yêu cầu http vì vậy chỉ cần tập tin đầu tiên nó sẽ được 10 yêu cầu HTTP. Hãy tưởng tượng nếu tôi có 1gb tệp, nó sẽ trở thành 1000 yêu cầu HTTP và làm chậm máy tính.

Đây là mã ví dụ:

 //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); 
     } 

và phần máy chủ cho nhận sẽ 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

Nếu bạn không muốn file của mình được chia thành nhiều phần, sau đó tại sao bạn chia chúng ở nơi đầu tiên? – Carsten

+0

Không, tôi cần chúng tách ra. vì 1. PHP có giới hạn tải lên (Tôi biết tôi có thể thay đổi giới hạn đó, nhưng đó không thực sự là giải pháp thực) 2. theo cách đó tôi có thể tải lên nhiều phần cùng một lúc, điều này sẽ làm cho nó nhanh hơn. – Harts

+0

thực sự là tập tin chia nhỏ cũng sẽ giúp tôi đạt được hồ sơ (trong trường hợp kết nối đột ngột xuống), người dùng không phải bắt đầu lại từ đầu một lần nữa – Harts

Trả lời

6

Sau khi đọc động lực của bạn trong bình luận của bạn Tôi muốn chỉ ra một vài 'quan niệm sai lầm'. Trước hết, đó là không phải nên chia nhỏ một tệp và tải lên tiếp theo tất cả các phần được chia tách cùng một lúc. Toàn bộ điểm chia tách tệp là không phải để vượt qua giới hạn tải lên PHP (nếu có, nên được thay đổi và có thể là giải pháp thực tế *), nhưng bằng cách thực hiện các phần khác nhau theo trình tự này cho phép tải trên máy tính của khách hàng ở mức tối thiểu, đặc biệt nếu bạn đang xem xét tải lên 1GB nội dung. Dù bằng cách nào, không có lý do gì để chia nhỏ một tệp và kết hợp nó trong một yêu cầu duy nhất (mặc dù điều này về mặt lý thuyết có thể với XMLHttpRequest2, nhưng nếu bạn có thể sử dụng XMLHttpRequest2 thì bạn không nên lo lắng về việc chia nhỏ tệp , vì nó cung cấp các điều khiển cần thiết để tải lên nhiều tệp một cách rõ ràng).

* Xin lưu ý rằng trong trường hợp bạn làm điều đó, bạn sẽ phải đảm bảo cài đặt bộ nhớ php được thiết lập đúng cách (để ngăn php cố tải hoàn toàn vào bộ nhớ trước khi ghi vào tệp tạm thời, nhưng không nên t xảy ra trên các phiên bản PHP gần đây với các cài đặt mặc định mà tôi tin). (Tôi cảm thấy bắt buộc phải thêm rằng tôi đã không làm việc với PHP và PHP tải lên trong một vài năm, vì vậy tôi có thể bị nhầm lẫn với nhận xét cuối cùng này)

Dù bằng cách nào, chunking các tập tin vào khoảng 5-25MB (tùy thuộc vào mức độ mong đợi của kết nối: P) + tải lên tuần tự (cộng với thanh tiến trình tốt nếu XMLHttpRequest2 có sẵn, nếu không thì một thanh tiến trình trên mỗi đoạn) có vẻ là một cách hợp lý để ngăn chặn trình duyệt bị quá tải. (Oh và, nếu bạn cần hỗ trợ trình duyệt cũ hơn, tôi sẽ thực sự khuyên bạn nên xem xét những người tải lên flash, vì mặc dù Apple đã thuyết phục đèn flash là điều xấu, trên phần lớn các máy tính cũ) sẽ mang lại trải nghiệm tốt nhất cho đến nay)

+0

thực sự chia nhỏ tập tin cũng sẽ giúp tôi đạt được hồ sơ (trong trường hợp kết nối đột ngột xuống), người dùng không phải bắt đầu lại từ đầu. Vì vậy, Dựa trên giải pháp của bạn, Bạn không nên tải lên đồng thời một ý tưởng hay? và tôi nên gắn bó với tải lên tuần tự? btw flash và java không phải là một lựa chọn vì tôi đang cố gắng tránh xa điều này, đó là lý do tại sao tôi sử dụng HTML5. Cảm ơn bạn – Harts

+0

Nó không phải là một lựa chọn "bởi vì" bạn đang cố gắng để có được từ nó? Đó không phải là lý do tôi hy vọng, vì bạn không nên chuyển sang HTML5 chỉ vì mục đích di chuyển (không có bất kỳ điều gì tốt hơn về nó vào lúc này, vì nó có hỗ trợ tồi tệ hơn so với tính khả dụng của flash). Dù sao đi nữa, đó là lý do tại sao tôi nói rằng việc chia nhỏ các tập tin sẽ là một ý tưởng hay trong kết luận của tôi và tùy thuộc vào chất lượng kết nối làm cho các khối càng lớn càng tốt, nhưng nếu bạn tải lên cùng một lúc, bạn sẽ mất tất cả các ưu điểm. (như tiếp tục tải lên cũng sẽ không thực tế) –

+0

Không, ý tôi là tôi có dự án được viết bằng Java (và đang hoạt động), và bây giờ tôi đang cố gắng viết lại nó trong HTML5 trong tương lai. Tôi biết tại thời điểm HTML5 vẫn không tốt như java hay flash – Harts

1

Trình tải lên Java [cụ thể là JumpLoader] - Tôi không nói "sử dụng chúng", nhưng tìm hiểu cách chúng hoạt động. Cho đến nay, thực hành tải lên tốt nhất mà tôi đã thấy là: 1) chia nhỏ tệp thành các phần có kích thước nhất định, 2) tải lên khối liên tục (bổ sung bằng cách cung cấp băm, nếu dữ liệu nhạy cảm), 3) khối liên kết ở phía máy chủ (nhưng xác minh tính toàn vẹn dữ liệu thông qua các băm, nếu bạn đang sử dụng chúng).

Vì vậy, bạn sẽ bỏ qua giới hạn max_upload_size của PHP. Nếu không, cá nhân tôi không thấy bất kỳ công đức nào tại sao một người nào đó nên chia dữ liệu thành nhiều phần ở vị trí đầu tiên.

0

Hãy thử điều này:

<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

khác nhau với mã của tôi là gì? Tôi không thể tìm thấy sự khác biệt? – Harts

Các vấn đề liên quan