HTML5 FileReader API 内存问题

HTML5 FileReader API Memory Issues

简而言之,我使用 HTML5 FileReader API 和 xhr post 编写了一个文件上传器,用于将 user-selected 文件上传到服务器。我的 client-side 代码有一些基本任务,包括从 selected 文件的 headers(这些是 DICOM 图像文件)中获取值并显示它们 prior 将文件发送到服务器、更新进度条等。我还有一些其他功能,包括压缩文件(如果它可以加快速度)等等。

很快,我注意到大文件占用了 的内存 (Chrome-specific)。如果数据集足够大,Chrome "Aw, Snap!" 就会完全崩溃。我已经实施了无数修复:详尽搜索内存泄漏、使用回调和小 queue 延迟读取和发送文件、一次只读取每个文件的 n 个块等。正如您想象的那样,这导致了一些相当大的 client-side JavaScript (实际上是 coffeescript)。在下面的 fiddle 中,我和一位同事将其简化为最基本的内容:以块的形式读取所有 selected 文件并为该二进制数据设置一个变量(让每个人都阅读解析解析的代码headers,必要时压缩,并发送每个块)。

https://jsfiddle.net/3nails4you/gsqzrk9g/8/,或见下文:

HTML:

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

JavaScript:

function slice() {

    var filesArr = document.getElementById('file').files;
    var index;
    for (index = 0; index < filesArr.length; index++) {
        readFile(filesArr[index]);
    }
}

function readFile(file) {

    var fr = new FileReader(),
        chunkSize = 2097152,
        chunks = Math.ceil(file.size / chunkSize),
        chunk = 0;

    function loadNext() {
        var start, end, blob;

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

        fr.onload = function (e) {
            // get file content
            var filestream = e.target.result;
            if (++chunk < chunks) {
                console.info(chunk);
                loadNext();
            }
        };
        blob = file.slice(start, end);
        fr.readAsBinaryString(blob);
    }
    loadNext();
}

我尝试了不同的读取方法(如 ArrayBuffer、DataURL)、许多不同的结构直至变量范围(例如仅声明 1 个 FileReader 并重用等),并尝试了许多不同的块大小以进行优化。当我 select 一个大约 1 GB 的特定数据集,跨越 16 个文件时,内存使用情况如下所示:

[编辑] 我还不能 post 图片,所以我只是描述一下。查看 Windows 任务管理器,chrome 进程正在使用 625,000 K 内存。

值得注意的是,如果我等待读取完成(控制台日志将停止输出),内存使用量将变为静态。如果此时我打开 JavaScript 控制台,内存使用率将下降到文件读取开始之前的水平。我怀疑打开控制台的行为会触发 Chrome 的垃圾 collection,或者类似的东西,但我不确定。

我发现了其他关于类似问题的问题,但所有这些问题的回答都是假设客户端实际上不需要使用文件的二进制数据.我绝对愿意-有什么建议吗?这仅仅是报告 Chromium 项目的错误吗?我的代码中是否存在我刚刚错过的明显错误?我通常倾向于怀疑后者,但 "opening the console clears the memory" 点继续让我感到厌烦——如果存在内存泄漏,真的会是这样吗?感谢阅读,感谢任何建议!

万一有人遇到同样的问题,我想我会分享我们发现的内容以缓解这种情况。

我最终购买了许可证并将 plupload 合并到我的 coffeescript 中。这有助于以这种方式解决内存问题:

首先,我创建了一个新的 plupload 对象,并设置了它的事件处理程序(BeforeUpload、UploadProgress 等)。它的 'Destroy' 处理程序调用 javascript 函数 nextUploader(),该函数创建另一个上传器对象并将下一部分文件排队。 destroy发生后,plupload对象的内存占用被成功回收,浏览器的内存占用保持在合理范围内。

如果有人想要 HTML5 文件读取和上传,我强烈推荐探索 plupload - 它非常容易使用,我们发现 Dropbox 也在使用它。