Загрузка файла HTML5 с несколькими индикаторами выполнения

Я загружаю несколько файлов через 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);
        }

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

Ответ 1

Ваш пример не работает должным образом, потому что вы не принимаете во внимание, что событие 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);

Ответ 2

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

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