11

FileReader は、複数の BLOB をプリロードするために繰り返し使用され、決して解放されないため、すべてのメモリを消費しているようです。消費されたメモリを強制的に解放する既知の方法はありますか? FileReader オブジェクトとその結果プロパティを null に設定しても機能しないようです。

アップデート:

サンプル コードは次のとおりです (ムービーなどの大きなファイルでテストしないと、タスク マネージャーで効果がわかりません)。

<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 バグ ( Bug 649150 - FormData 経由で送信された場合、Blob にファイル名がない) を克服するための単なる実験です。

4

2 に答える 2

4

代わりに次のようにしてみてください。

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 を使用すると、他の読み取りと重複しないようになります... (明らかに、インクリメントをもう少しうまく修正できますが、アイデアは得られます...)

于 2013-07-31T16:28:22.547 に答える
3

実際には FileReader オブジェクトを適切に再利用していないことが判明したため、バグは INVALID としてマークされました。

これは、メモリと CPU を占有しないパターンです。

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、これは関連していますが、この場合の悪ではありません。

これを私に知らせてくれたカイル・ヒューイに感謝します:)

于 2011-08-24T08:23:07.863 に答える