FileReader memory leak

by andy250

HTML

<input id="fu" type="file" multiple="multiple" />
<br/>
<br/>
<div class="sent"></div>
<br/>
<div class="pb"></div>

CSS

.pb {
    height: 10px;
    width: 0%;
    background-color: green;
}

JavaScript

var reader = new FileReader();

var fu = {
    file: null,
    chunks: [],
    chunkSize: 5000000,
    chunkNo: 0,
    totalChunks: 0,

    chunkify: function() {
        fu.totalChunks = Math.ceil(fu.file.size / fu.chunkSize);
        var seq = 0;
        while (seq < fu.totalChunks) {
            var start = seq * fu.chunkSize;
            var end = Math.min(start + fu.chunkSize, fu.file.size);
            if (start <= end) {
                fu.chunks.push(fu.file.slice(start, end, fu.file.type));
            }
            seq++;
        }
    },

    select: function(evt) {
        evt.stopPropagation();
        evt.preventDefault();
        fu.file = evt.target.files ? evt.target.files[0] : evt.dataTransfer ? evt.dataTransfer.files[0] : null;
        fu.chunkify();
        fu.chunkNo = 0;
        fu.processChunk(fu.chunks.shift());
    },

    sendToServer: function(chunk, hash, callback) {
        setTimeout(function() {
            $('.pb').width((fu.chunkNo / fu.totalChunks * 100).toFixed(1) + '%');
            $('.sent').text((fu.chunkNo*fu.chunkSize/1024/1024).toFixed(1) + 'MB / ' + (fu.file.size/1024/1024) .toFixed(1) + 'MB');
            callback();
        }, 200); // simulate server call and a short timeout
    },

    getHash: function(blob, callback) {
        reader.onloadend = function(e) {
            var hash = 'hash_' + fu.chunkNo.toString() + '_' + e.target.result.byteLength.toString(); // dummy hashing
            callback(hash);
        };
        reader.readAsArrayBuffer(blob);
    },

    processChunk: function(chunk) {
        if (chunk) {
            fu.chunkNo++;
            fu.getHash(chunk, function(hash) {
                fu.sendToServer(chunk, hash, function() {
                    fu.processChunk(fu.chunks.shift());
                });
            });
        }
    }
}

$(document).ready(function() {
    var input = $("body #fu");
    input.get(0).addEventListener('change', fu.select, false);
});