2013-04-12 18 views
12

Sto tentando di caricare alcuni file di grandi dimensioni sul server utilizzando XMLHttpRequest e file.slice.
Sono riuscito a farlo con l'aiuto di documentazione e altri vari collegamenti.
Dal momento che il caricamento di file di grandi dimensioni è un lavoro molto lungo, vorrei fornire all'utente una barra di avanzamento.
Dopo alcune letture che ho trovato su un example che, in teoria, fa esattamente quello che mi serve.
Prendendo il codice di esempio e adattandolo alle mie esigenze ho raggiuntoBarra di avanzamento durante il caricamento di file di grandi dimensioni con 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; 
} 
}; 

La chiamata è come (senza le convalide)

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

Il mio problema è che l'evento progress non attiva.
Ho provato xhr.addEventListener e con xhr.upload.addEventListener (ciascuno alla volta e entrambi contemporaneamente) per l'evento progress ma non si attiva mai. Gli eventi onreadystatechange e load si attivano correttamente.

Io apprezzo molto di aiuto con quello che sto facendo male

Aggiornamento
Dopo molti tentativi ho riuscire a simulare un progresso, ma ho funzionato in un altro problema: interfaccia utente di Chrome non viene aggiornato durante il caricamento.
Il codice simile a questo ora

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 + '%'; 
    } 
}; 


Update 2
sono riuscito a risolvere il problema e simulare una barra di avanzamento che funziona in cromo troppo.
ho aggiornato il codice precedente con quello che funziona.
È possibile effettuare il bar 'rinfrescare' il più delle volte, riducendo le dimensioni del pezzo caricato in un momento Tahnk per il vostro aiuto

+0

Si sta utilizzando una funzione per abbreviare le chiamate 'document.getElementById'? Sembra che sia ciò che '$ get()' sta facendo, ma non lo vedo definito da nessuna parte. – user1091949

+0

si. ma non penso che sia questo il problema funziona perfettamente nell'evento load e lo imposta al 100% – Cioby

+0

@Cioby potresti caricare un JSFiddle della tua soluzione? – frogbandit

risposta

3

Come indicato nel https://stackoverflow.com/a/3694435/460368, si poteva fare:

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

e

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

l'evento progress non è ancora attivato; – Cioby

+0

@Cioby Hai provato a farlo in modo asincrono? 'xhr.open ('POST', upload.pageName, true);' http://www.w3.org/TR/XMLHttpRequest/#the-open()-method – Shikiryu

+0

@Cioby e hai provato http: // stackoverflow.com/a/4943774/460368? – Shikiryu

0

c'è la mia soluzione:

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


} 
Problemi correlati