Ich versuche, einige große Dateien mit XMLHttpRequest und file.slice auf den Server hochzuladen.
Ich habe es mit Hilfe von Dokumentationen und anderen verschiedenen Links geschafft.
Da das Hochladen großer Dateien eine langwierige Aufgabe ist, möchte ich dem Benutzer einen Fortschrittsbalken zur Verfügung stellen.
Nach einigen weiteren Lesungen bin ich auf eine gestoßen Beispiel das macht theoretisch genau das, was ich brauche.
Indem ich den Beispielcode nahm und ihn an meine Bedürfnisse anpasste, erreichte ich
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;
}
};
Der Anruf ist wie (ohne die Validierungen)
upload.upload(document.getElementById("#upload").files[0]);
Mein Problem ist, dass das Fortschrittsereignis nicht ausgelöst wird.
Ich habe xhr.addEventListener und mit xhr.upload.addEventListener (jeweils und beide gleichzeitig) für das Fortschrittsereignis ausprobiert, aber es wird nie ausgelöst. Die Ereignisse onreadystatechange und load werden problemlos ausgelöst.
Ich würde mich sehr über Hilfe bei dem, was ich falsch mache, freuen
Aktualisieren
Nach vielen Versuchen ist es mir gelungen, einen Fortschritt zu simulieren, aber ich bin auf ein anderes Problem gestoßen: Die Benutzeroberfläche von Chrome wird während des Uploads nicht aktualisiert.
Der Code sieht jetzt so aus
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 + '%';
}
};
Aktualisierung 2
Ich habe es geschafft, es zu beheben und einen Fortschrittsbalken zu simulieren, der auch in Chrome funktioniert.
Ich habe das vorherige Codebeispiel mit dem aktualisiert, das funktioniert.
Sie können die Leiste häufiger „aktualisieren“, indem Sie die Größe des jeweils hochgeladenen Chunks verringern. Danke für Ihre Hilfe
Verwenden Sie eine Funktion zum Kürzen?
document.getElementById
Anrufe? Es sieht so aus, als wäre das was$get()
tut, aber ich sehe es nirgendwo definiert.– Benutzer1091949
12. April 2013 um 8:21 Uhr
ja. aber ich glaube nicht, dass das das problem ist. es funktioniert gut im Lastereignis und setzt es auf 100%
– Cioby
12. April 2013 um 8:59 Uhr
@Cioby könnten Sie ein JSFiddle Ihrer Lösung hochladen?
– Froschbandit
24. Juni 2016 um 22:18 Uhr