Можно ли почистить память после FileReader? - PullRequest
8 голосов
/ 21 августа 2011

FileReader, кажется, потребляет всю память, так как он многократно используется для предварительной загрузки нескольких BLOB-объектов и никогда не освобождает ее. Любой известный способ заставить его освободить потребляемую память? Установка объекта FileReader и его свойства результата в null, похоже, не работает.

UPDATE:

Вот пример кода (протестируйте его на больших файлах, таких как фильм, или вы не заметите эффект в диспетчере задач):

<input id="file" type="file" onchange="sliceMe()" />

<script>
function sliceMe() {
    var file = document.getElementById('file').files[0], 
        fr,
        chunkSize = 2097152, 
        chunks = Math.ceil(file.size / chunkSize), 
        chunk = 0;

    function loadNext() {
       var start, end,
           blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice;

       start = chunk * chunkSize;
       end = start + chunkSize >= file.size ? file.size : start + chunkSize;

       fr = new FileReader;
       fr.onload = function() {      
          if (++chunk < chunks) {
             // shortcut - in production upload happens and then loadNext() is called
             loadNext(); 
          }
       };
       fr.readAsBinaryString(blobSlice.call(file, start, end));
    }

    loadNext();
}
</script>

Я пытался каждый раз создавать новый экземпляр FileReader, но проблема все еще остается. Я подозреваю, что это может быть вызвано круговой природой шаблона, но я не уверен, какой другой шаблон можно использовать в этом случае.

Я проверил этот код как в Firefox, так и в Chrome, и Chrome, кажется, обрабатывает его более изящно - он очищает память после каждого цикла и работает очень быстро. Но ирония ситуации заключается в том, что Chrome вообще не нужно использовать этот код. Это всего лишь эксперимент по преодолению ошибки Gecko 6 - FormData + Blob ( Ошибка 649150 - У блобов нет имени файла, если они отправлены через FormData ).

Ответы [ 2 ]

4 голосов
/ 31 июля 2013

Попробуйте вместо этого вот так:

function sliceMe() {
        var file = document.getElementById('file').files[0],
        fr = new FileReader,
        chunkSize = 2097152,
        chunks = Math.ceil(file.size / chunkSize),
        chunk = 0;

    function loadNext() {
       var start, end,
           blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice;

       start = chunk * chunkSize;
       end = start + chunkSize >= file.size ? file.size : start + chunkSize;

       fr.onload = function() {      
          if (++chunk < chunks) {
             //console.info(chunk);
          }
       };
       fr.onloadend = function(e) {      
          loadNext(); // shortcut here
       };
       fr.readAsBinaryString(blobSlice.call(file, start, end));
    }

    loadNext();
}

Onloadend не позволит вам перекрывать другие чтения ... (Очевидно, вы можете исправить приращение немного лучше, но вы поняли идею ...)

3 голосов
/ 24 августа 2011

Ошибка помечена как НЕДЕЙСТВИТЕЛЬНАЯ, поскольку оказалось, что я на самом деле не использовал объект FileReader должным образом.

Вот шаблон, который не загружает память и процессор:

function sliceMe() {
    var file = document.getElementById('file').files[0],
        fr = new FileReader,
        chunkSize = 2097152,
        chunks = Math.ceil(file.size / chunkSize),
        chunk = 0;

    function loadNext() {
       var start, end,
           blobSlice = File.prototype.mozSlice || File.prototype.webkitSlice;

       start = chunk * chunkSize;
       end = start + chunkSize >= file.size ? file.size : start + chunkSize;

       fr.onload = function() {      
          if (++chunk < chunks) {
             //console.info(chunk);
             loadNext(); // shortcut here
          }
       };
       fr.readAsBinaryString(blobSlice.call(file, start, end));
    }

    loadNext();
}

Подано еще одно сообщение об ошибке: https://bugzilla.mozilla.org/show_bug.cgi?id=681479,, которое связано, но не зло в данном случае.

Спасибо Кайлу Хьюи за то, что он привлек мое внимание :)

...