Загрузка файла HTML5 с несколькими индикаторами выполнения - PullRequest
8 голосов
/ 18 июля 2011

Я загружаю несколько файлов через XmlHTTPRequest и HTML5. У меня загрузка работает нормально, но я хотел бы иметь индикатор выполнения для каждой загрузки файла. Однако код, который я использую, использует последнюю индикатор выполнения для ВСЕХ загрузок файла, а не каждую загрузку, используя свою собственную индикатор выполнения. Так что это в основном визуально на стороне клиента, но это действительно раздражает меня. По какой-то причине я предполагаю, что событие, которое прикрепляет ход загрузки файла, перезаписывается и использует последний индикатор выполнения. Вот мой код:

var files = event.dataTransfer.files;

    // iterate over each file to upload, send a request, and attach progress event
    for (var i = 0, file; file = files[i]; i++) {
        var li = $("<li>" + file.name + "<div class='progressbar'></div></li>");

        // add the LI to the list of uploading files
        $("#uploads").append(li);

        // fade in the LI instead of just showing it
        li.hide().fadeIn();

        var xhr = new XMLHttpRequest();

            xhr.upload.addEventListener('progress', function(e) {
                var percent = parseInt(e.loaded / e.total * 100);
                li.find(".progressbar").width(percent);
            }, false);

            // check when the upload is finished
            xhr.onreadystatechange = stateChange;

            // setup and send the file
            xhr.open('POST', '/attachments', true);
            xhr.setRequestHeader('X-FILE-NAME', file.name);
            xhr.send(file);
        }

Я предполагаю, что правильное "li" не читается должным образом событием "progress". Я подозреваю, что есть какое-то связывание, которое я должен сделать, чтобы указать событию "progress" использовать определенную переменную, поскольку она "li", но я не уверен, что мне не хватает.

Ответы [ 2 ]

16 голосов
/ 18 июля 2011

Ваш пример не работает должным образом, потому что вы не учитываете, что событие xhr progress происходит, когда все элементы списка уже созданы.Однако есть много способов заставить ваш пример работать.Идея состоит в том, чтобы дать xhr знать, с каким именно элементом списка он имеет дело.Например, используйте этот код (я не проверял, работает ли он. Цель этого кода - описать идею):

var xhr = new XMLHttpRequest();
xhr.upload.li = li;
xhr.upload.addEventListener('progress', function(e) {
    var percent = parseInt(e.loaded / e.total * 100);
    this.li.find(".progressbar").width(percent);
}, false);
7 голосов
/ 14 января 2012

Я думаю, что нашел решение этой проблемы. Похоже, работает на некоторых из моих тестов. Я не очень хорош в английском, поэтому я просто поделюсь своим примером сценария. Если вы зададите любой вопрос, я постараюсь объяснить больше:)

// This is input object which type of file.  
var uploader = document.getElementById("fileUploader"); 

// We'll send a new post for each file.
for(var i=0, j=uploader.files.length; i<j; i++)
{
    var uploaderForm = new FormData(); // Create new FormData
    uploaderForm.append("action","upload"); // append extra parameters if you wish.
    uploaderForm.append("up_file",uploader.files[i]); // append the next file for upload

    var xhr = new XMLHttpRequest();

    xhr.addEventListener("loadstart", function(e){
        // generate unique id for progress bars. This is important because we'll use it on progress event for modifications
        this.progressId = "progress_" + Math.floor((Math.random() * 100000)); 

        // append progress elements to somewhere you want
        $("body").append('<div id="' + this.progressId + '" class="myCustomProgressBar" ></div>');
    });
    xhr.addEventListener("progress", function(e){
        var total = e.total;
        var loaded = e.loaded;
        var percent = (100 / total) * loaded; // Calculate percentage of loaded data

        // I animate progress object. Notice that i use "this.progressId" which i created on loadstart event.
        $("#" + this.progressId).animate({"width":300 * (percent / 100)}, 800);
    });

    xhr.open("POST","index.php");
    xhr.send(uploaderForm);
}
...