2012-06-08 13 views
13

Próbuję zaimplementować pasek postępu przesyłania w HTML5, korzystając z obsługi poziomu 2 dla zdarzeń postępu XMLHttpRequest.Dlaczego XMLHttpRequest ProgressEvent.lengthComputable może być fałszem?

W każdym przykładzie widać, metoda jest dodanie detektora zdarzeń dla zdarzenia progress tak:

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

Takie przykłady zdają się zakładać, że event.lengthComputable będzie prawdziwa. Przecież na pewno przeglądarka zna długość wysyłanego zapytania?

Bez względu na to, co robię, event.lengthComputable jest fałszywe. Testowałem to w Safari 5.1.7 i Firefox 12, oba na OSX.

Moja strona jest zbudowana przy użyciu Django, i mam ten sam problem w moich konfiguracjach programistycznych i produkcyjnych.

pełny kod używam do generowania przesłać formularz jest pokazany poniżej (przy użyciu 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; 
}); 

Byłem łzawienie włosy się godzinami na to. Każda pomoc doceniona!

+0

I napotkał ten problem, too. Wydaje się, że FormData() sprawia, że ​​lengthComputable == false. – est

Odpowiedz

30

Hej Znalazłem the answer z @ComFreek:

zrobiłem ten sam błąd.

Linia pisałem było:

xhr.onprogress = uploadProgress; 

Prawidłowe jeden powinien być

xhr.upload.onprogress = uploadProgress; 
+2

Dzięki za tę wskazówkę! Trudno znaleźć ... – Gregoire

+1

Tysiące razy dziękuję! Pracował jak urok! – Alex

+0

ya mój bohaterze, ale powinienem przeczytać bardziej poprawnie, że wiedziałbym o tym wcześniej: D – Can

1

Miałem również problem z wysyłaniem wielu dużych plików przy użyciu AJAX (xmlhttprequest).

Znaleziono rozwiązanie i tutaj jest cały skrypt, którego używam. Wszystko, co potrzebne jest, aby postawić następny wiersz na stronie HTML:

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

i wykorzystać kolejny skrypt:

<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> 

Twój wynik będzie w konsoli

Powiązane problemy