2013-04-12 16 views
12

Próbuję przesłać kilka dużych plików na serwer przy użyciu XMLHttpRequest i file.slice.
Udało mi się to zrobić za pomocą dokumentacji i innych różnych linków.
Ponieważ przesyłanie dużych plików jest długotrwałym zadaniem, chciałbym udostępnić użytkownikowi pasek postępu.
Po kilku lekturach natknąłem się na example, który, teoretycznie, robi dokładnie to, czego potrzebuję.
Podejmując przykładowego kodu i dostosowanie go do moich potrzeb i osiągnąłPasek postępu podczas przesyłania dużych plików za pomocą XMLHttpRequest

var upload = 
{ 
blobs: [], 
pageName: '', 
bytesPerChunk: 20 * 1024 * 1024, 
currentChunk: 0, 
loaded: 0, 
total: 0, 
file: null, 
fileName: "", 

uploadChunk: function (blob, fileName, fileType) { 
    var xhr = new XMLHttpRequest(); 

    xhr.onreadystatechange = function() { 
     if (xhr.readyState == 4) { 
      if (xhr.responseText) { 
       // alert(xhr.responseText); 
      } 
     } 
    }; 

    xhr.addEventListener("load", function (evt) { 
     $("#dvProgressPrcent").html("100%"); 
     $get('dvProgress').style.width = '100%'; 
    }, false); 

    xhr.addEventListener("progress", function (evt) { 
     if (evt.lengthComputable) { 
      var progress = Math.ceil(((upload.loaded + evt.loaded)/upload.total) * 100); 
      $("#dvProgressPrcent").html(progress + "%"); 
      $get('dvProgress').style.width = progress + '%'; 
     } 
    }, false); 

    xhr.upload.addEventListener("progress", function (evt) { 
     if (evt.lengthComputable) { 
      var progress = Math.ceil(((upload.loaded + evt.loaded)/upload.total) * 100); 
      $("#dvProgressPrcent").html(progress + "%"); 
      $get('dvProgress').style.width = progress + '%'; 
     } 
    }, false); 

    xhr.open('POST', upload.pageName, false); 

    xhr.setRequestHeader("Content-Type", "multipart/form-data"); 
    xhr.setRequestHeader("X-File-Name", fileName); 
    xhr.setRequestHeader("X-File-Type", fileType); 
    xhr.send(blob); 
}, 
upload: function (file) { 
    var start = 0; 
    var end = 0; 
    var size = file.size; 

    var date = new Date(); 
    upload.fileName = date.format("dd.MM.yyyy_HH.mm.ss") + "_" + file.name; 

    upload.loaded = 0; 
    upload.total = file.size; 

    while (start < size) { 
     end = start + upload.bytesPerChunk; 
     if (end > size) { 
      end = size; 
     } 

     var blob = file.slice(start, end); 
     upload.uploadChunk(blob, upload.fileName, file.type); 
     start = end; 
     upload.loaded += start; 
    } 

    return upload.fileName; 
} 
}; 

Wezwanie jest jak (bez walidacji)

upload.upload(document.getElementById("#upload").files[0]); 

Moim problemem jest to, że zdarzenie nie powoduje postęp.
Próbowałem już xhr.addEventListener i xhr.upload.addEventListener (każdy naraz i oba naraz) dla zdarzenia postępu, ale nigdy się nie uruchamia. Zdarzenia onreadystatechange i load wyzwalają dobrze.

Będę bardzo wdzięczny pomóc z tym, co robię źle

Aktualizacja
Po wielu próbach mam zarządzać symulować postęp ale już wpadł na inny problem: Chrome UI nie jest aktualizowana w czasie przesłanie.
Kod wygląda to teraz

var upload = 
{ 
    pageName: '', 
    bytesPerChunk: 20 * 1024 * 1024, 
    loaded: 0, 
    total: 0, 
    file: null, 
    fileName: "", 

    uploadFile: function() { 
     var size = upload.file.size; 

     if (upload.loaded > size) return; 

     var end = upload.loaded + upload.bytesPerChunk; 
     if (end > size) { end = size; } 

     var blob = upload.file.slice(upload.loaded, end); 

     var xhr = new XMLHttpRequest(); 

     xhr.open('POST', upload.pageName, false); 

     xhr.setRequestHeader("Content-Type", "multipart/form-data"); 
     xhr.setRequestHeader("X-File-Name", upload.fileName); 
     xhr.setRequestHeader("X-File-Type", upload.file.type); 

     xhr.send(blob); 

     upload.loaded += upload.bytesPerChunk; 

     setTimeout(upload.updateProgress, 100); 
     setTimeout(upload.uploadFile, 100); 
    }, 
    upload: function (file) { 
     upload.file = file; 

     var date = new Date(); 
     upload.fileName = date.format("dd.MM.yyyy_HH.mm.ss") + "_" + file.name; 

     upload.loaded = 0; 
     upload.total = file.size; 

     setTimeout(upload.uploadFile, 100); 


     return upload.fileName; 
    }, 
    updateProgress: function() { 
     var progress = Math.ceil(((upload.loaded)/upload.total) * 100); 
     if (progress > 100) progress = 100; 

     $("#dvProgressPrcent").html(progress + "%"); 
     $get('dvProgress').style.width = progress + '%'; 
    } 
}; 


Aktualizacja 2
udało mi się go naprawić i symulacji pasek postępu, który działa w Chrome zbyt.
Zaktualizowałem poprzedni przykład kodu z tym, który działa.
Można zrobić pasek „odświeżyć” częściej poprzez zmniejszenie rozmiaru fragmentu przesłanego naraz tahnk za pomoc

+0

Czy używasz funkcji skracania wywołań 'document.getElementById'? Wygląda na to, że '$ get()' robi, ale nie widzę go zdefiniowany w dowolnym miejscu. – user1091949

+0

tak. ale nie sądzę, że to jest problem. to działa dobrze w przypadku obciążenia i ustawia go na 100% – Cioby

+0

@Cioby mógłbyś przesłać JSFiddle swojego rozwiązania? – frogbandit

Odpowiedz

3

Jak stwierdzono w https://stackoverflow.com/a/3694435/460368, można zrobić:

if(xhr.upload) 
    xhr.upload.onprogress=upload.updateProgress; 

i

updateProgress: function updateProgress(evt) 
{ 
    if (evt.lengthComputable) { 
     var progress = Math.ceil(((upload.loaded + evt.loaded)/upload.total) * 100); 
     $("#dvProgressPrcent").html(progress + "%"); 
     $get('dvProgress').style.width = progress + '%'; 
    } 
} 
+1

zdarzenie progress nie jest jeszcze wyzwalane; – Cioby

+0

@Cioby Czy próbowałeś robić to w sposób asynchroniczny? 'xhr.open ('POST', upload.pageName, true);' http://www.w3.org/TR/XMLHttpRequest/#the-open()-method – Shikiryu

+0

@Cioby i czy próbowałeś http: // stackoverflow.com/a/4943774/460368? – Shikiryu

0
Nie

jest moje rozwiązanie:

function addImages(id) 
{ 


var files= $("#files").prop("files"); 
var file = files[loopGallery]; 
var cList= files.length; 

var fd = new FormData(); 

fd.append("file", file); 
fd.append("galerie", id); 


var xhr = new XMLHttpRequest(); 

xhr.open("POST", "moduls/galerie/uploadimages.php", true); 

xhr.upload.onprogress = function(e) 
{ 

var percentComplete = Math.ceil((e.loaded/e.total) * 100); 

$("#progress").css("display",""); 

$("#progressText").text((loopGallery+1)+" z "+cList); 
$("#progressBar").css("width",percentComplete+"%"); 

}; 


xhr.onload = function() 
{ 

if(this.status == 200) 
{ 
    $("#progressObsah").load("moduls/galerie/showimages.php?ids="+id); 

    if((loopGallery+1) == cList) 
    { 
     loopGallery = 0; 

    } 
    else 
    { 
    $("#progressBar").css("width", "0%"); 
loopGallery++; 
addImages(id); 
} 

}; 

}; 

if(cList < 1) 
{ 

} 
else 
{ 
xhr.send(fd); 
} 


} 
Powiązane problemy