2012-06-08 16 views
13

Estoy tratando de implementar una barra de progreso de carga de la manera HTML5, mediante el uso del nivel 2 de XMLHttpRequest para eventos de progreso.¿Por qué XMLHttpRequest ProgressEvent.lengthComputable podría ser falso?

En todos los ejemplos que se ve, el método consiste en añadir un detector de eventos para el evento progress, así:

req.addEventListener("progress", function(event) { 
    if (event.lengthComputable) { 
     var percentComplete = Math.round(event.loaded * 100/event.total); 
     console.log(percentComplete); 
    } 
}, false); 

Tales ejemplos siempre parecen asumir que event.lengthComputable será verdad. Después de todo, ¿el navegador conoce la duración de la solicitud que está enviando, seguramente?

No importa lo que haga, event.lengthComputable es falso. He probado esto en Safari 5.1.7 y Firefox 12, ambos en OSX.

Mi sitio está construido usando Django, y me da el mismo problema en mis dev y producción configuraciones.

El código completo que estoy usando para generar el formulario de carga se muestra a continuación (usando jQuery):

form.submit(function() { 
    // Compile the data. 
    var data = form.serializeArray(); 
    data.splice(0, 0, { 
     name: "file", 
     value: form.find("#id_file").get(0).files[0] 
    }); 
    // Create the form data. 
    var fd = new FormData(); 
    $.each(data, function(_, item) { 
     fd.append(item.name, item.value); 
    }); 
    // Submit the data. 
    var req = new XMLHttpRequest(); 
    req.addEventListener("progress", function(event) { 
     if (event.lengthComputable) { 
      var percentComplete = Math.round(event.loaded * 100/event.total); 
      console.log(percentComplete); 
     } 
    }, false); 
    req.addEventListener("load", function(event) { 
     if (req.status == 200) { 
      var data = $.parseJSON(event.target.responseText); 
      if (data.success) { 
       console.log("It worked!") 
      } else { 
       console.log("It failed!") 
      } 
     } else { 
      console.log("It went really wrong!") 
     } 
    }, false); 
    req.addEventListener("error", function() { 
     console.log("It went really really wrong!") 
    }, false); 
    req.open("POST", "/my-bar/media/add/"); 
    req.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 
    req.send(fd); 
    // Don't really submit! 
    return false; 
}); 

he estado rompiendo mi pelo por horas en esto. Cualquier ayuda apreciada!

+0

me encontré con este problema, también. Parece que FormData() hace que lengthComputable == sea falso. – est

Respuesta

30

Hey He encontrado the answer de @ComFreek:

que cometió el mismo error.

La línea que escribí fue:

xhr.onprogress = uploadProgress; 

la correcta debería ser

xhr.upload.onprogress = uploadProgress; 
+2

¡Gracias por este consejo! Es difícil de encontrar ... – Gregoire

+1

¡Mil veces gracias! ¡Trabajado como un encanto! – Alex

+0

ya mi héroe, pero debería leer más correctamente que lo hubiera sabido antes: D – Can

1

También tuve un problema con el envío de múltiples archivos de gran tamaño utilizando AJAX (XMLHttpRequest).

Encontré una solución y aquí está todo el script que uso. Todo lo que necesita es colocar la siguiente línea en su página HTML:

<input type="file" multiple name="file" id="upload_file" onchange="handleFiles(this)"> 

y el uso de comandos siguiente:

<script type="text/javacript"> 
    var filesArray; 
    function sendFile(file) 
    { 
     var uri = "<URL TO PHP FILE>"; 
     var xhr = new XMLHttpRequest(); 
     var fd = new FormData(); 

     var self = this; 

     xhr.upload.onprogress = updateProgress; 
     xhr.addEventListener("load", transferComplete, false); 
     xhr.addEventListener("error", transferFailed, false); 
     xhr.addEventListener("abort", transferCanceled, false); 
     xhr.open("POST", uri, true); 
     xhr.onreadystatechange = function() { 
      if (xhr.readyState == 4 && xhr.status == 200) { 
       alert(xhr.responseText); // handle response. 
      } 
     }; 
     fd.append('myFile', file); 
     // Initiate a multipart/form-data upload 
     xhr.send(fd); 
    } 
    function updateProgress (oEvent) 
    { 
     if (oEvent.lengthComputable) 
     { 
      var percentComplete = oEvent.loaded/oEvent.total; 
      console.log(Math.round(percentComplete*100) + "%"); 
     } else { 
      // Unable to compute progress information since the total size is unknown 
      console.log("Total size is unknown..."); 
     } 
    } 

    function transferComplete(evt) 
    { 
     alert("The transfer is complete."); 
    } 

    function transferFailed(evt) 
    { 
     alert("An error occurred while transferring the file."); 
    } 

    function transferCanceled(evt) 
    { 
     alert("The transfer has been canceled by the user."); 
    } 
    function handleFiles(element) 
    { 
     filesArray = element.files; 
     if (filesArray.length > 0) 
     { 
      for (var i=0; i<filesArray.length; i++) 
      { 
       sendFile(filesArray[i]); 
      } 
      filesArray = ''; 
     } 
    } 
    </script> 

Su resultado será en la consola

Cuestiones relacionadas