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
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
tak. ale nie sądzę, że to jest problem. to działa dobrze w przypadku obciążenia i ustawia go na 100% – Cioby
@Cioby mógłbyś przesłać JSFiddle swojego rozwiązania? – frogbandit