2012-05-24 8 views
5

Utilizando fragmentación HTML5, pude cargar archivos con una pieza más pequeña. Pero el problema comienza cuando comenzó a usar múltiples solicitudes HTTP POST que causarán que la computadora se desacelere o probablemente se bloquee. ¿Hay alguna forma de tener el archivo dividido bajo una solicitud http ... así que si tengo 5 archivos sería solo 5 solicitud HTTP aunque utilizo la división html5Cómo cargar archivos múltiples en 1 solicitud HTTP

por ejemplo: si cargo 5 archivos, cada archivo se dividirá a 1mb, así que si el primer archivo es 10mb, entonces se convertirán en 10 piezas de 1mb. Y el problema es que cada fragmento tendrá menos de 1 solicitud HTTP, por lo que solo el primer archivo será 10 solicitudes HTTP. Imagine que si tengo archivos de 1 gb, se convertirá en 1000 solicitudes HTTP y ralentizará la computadora.

Esto es código de ejemplo:

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

y la parte del servidor de recepción habrá 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

Si no desea que los archivos divididos en varias partes, entonces ¿por qué se les dividirá en el primer lugar? – Carsten

+0

No, los necesito para dividir. porque 1. PHP tiene un límite de carga (sé que puedo cambiar ese límite, pero esa no es realmente una solución real) 2. de esa manera puedo subirlo varias piezas a la vez, lo cual lo hará más rápido. – Harts

+0

en realidad el archivo dividido también me ayudará a lograr la reanudación del archivo (en caso de que la conexión se desconecte repentinamente), el usuario no tiene que volver a empezar desde el principio – Harts

Respuesta

6

Después de leer su motivación en su comentario que me gustaría señalar una algunos 'conceptos erróneos'. En primer lugar, es no recomendable dividir un archivo y luego subir todas las partes divididas a la vez. El punto de dividir un archivo de seguridad de todo es no para eludir el límite de PHP para subir (que, en su caso, debe ser cambiado y que puede ser una solución real *), sino más bien al hacer las diferentes partes secuencialmente este permite que la carga en la computadora cliente sea mínima, especialmente si está considerando cargar 1GB de contenido. De cualquier manera, no hay ninguna razón para dividir un archivo y luego combinarlo en una sola solicitud (aunque esto sería teóricamente posible con XMLHttpRequest2, pero si puede usar XMLHttpRequest2, entonces no debería preocuparse de dividir el archivo de ninguna manera , ya que proporciona los controles necesarios para cargar múltiples archivos limpiamente).

* Tenga en cuenta que en caso de hacerlo deberá asegurarse de que su configuración de memoria php esté correctamente configurada (para evitar que php intente cargarla completamente en la memoria antes de escribirla en un archivo temporal, pero esto no debería sucede en versiones recientes de PHP con la configuración predeterminada, creo). (Me siento obligado a agregar que no he trabajado con cargas de PHP y PHP durante algunos años, por lo que podría estar muy equivocado con este último comentario)

De cualquier forma, dividiendo los archivos en 5-25MB (dependiendo de qué tan bueno espere que sea la conexión: P) + cargas secuenciales (más una agradable barra de progreso si XMLHttpRequest2 está disponible, de lo contrario una barra de progreso por fragmento) parece un camino sensato mientras evita que el navegador se sobrecargue. (Ah, y si necesita soportar navegador más antiguo, podría realmente aconsejarle que mire en los cargadores de flash, porque a pesar de que Apple predique flash para ser malvado, en la mayoría de las computadoras (desactualizadas) le dará la mejor experiencia de lejos)

+0

en realidad el archivo dividido también me ayudará a recuperar el archivo (en caso de que la conexión se desconecte repentinamente), el usuario no tiene que volver a empezar desde el principio. Por lo tanto, según su solución, ¿no es una buena idea cargar simultáneamente? y debería seguir cargando secuencialmente? Por cierto, Flash y Java no son una opción porque estoy intentando alejarme de esto, es por eso que estoy usando HTML5. Gracias – Harts

+0

No es una opción "porque" estás tratando de alejarte de eso? Esa no es la razón por la que espero, ya que no debería pasar a HTML5 solo por el mero hecho de moverse (no hay nada intrínsecamente mejor en este momento, ya que tiene peor soporte que la disponibilidad de flash). No importa, en cuanto a la reanudación de la carga de archivos, por eso dije que dividir los archivos sería una buena idea en mi conclusión y que dependiendo de la calidad de la conexión hiciera los pedazos lo más grandes posible, pero si los cargaba simultáneamente, perdería todas las ventajas (como reanudar la carga también sería poco realista) –

+0

No, quiero decir que ya tengo el proyecto escrito en Java (y en funcionamiento), y ahora estoy tratando de volver a escribirlo en HTML5 para el futuro. Sé que en este momento HTML5 aún no es tan bueno como Java o Flash – Harts

1

cargadores de Java [a saber, JumpLoader] - No estoy diciendo "utilízalos", pero aprende cómo funcionan. Hasta ahora, la mejor práctica de carga que he visto es: 1) dividir archivos en trozos de cierto tamaño, 2) cargar trozos secuencialmente (adicionalmente proporcionando hash de trozos, si los datos son sensibles), 3) unir trozos en el lado del servidor (pero verifique la integridad de los datos mediante hashes, si los está usando).

Por lo tanto, se saltará la restricción de max_upload_size de PHP. De lo contrario, personalmente no veo ningún mérito por el cual alguien debería dividir los datos en fragmentos en primer lugar.

0

Prueba esto:

<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

¿cuál es la diferencia con mi código? Parece que no puedo encontrar la diferencia? – Harts

Cuestiones relacionadas