FileReader之后可以清理内存吗?

发布于 2024-11-30 15:47:54 字数 1486 浏览 0 评论 0原文

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 的实验(Bug 649150 - Blob 没有如果通过 FormData 发送,则为文件名)。

FileReader seems to consume all the memory as it is repeatedly used to preload multiple blobs, and never frees it. Any known way to force it to release consumed memory? Setting FileReader object and it's result property to null doesn't seem to work.

UPDATE:

Here is a sample code (test it on a big files, like movie, or you won't notice the effect in task manager):

<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>

I tried to create fresh FileReader instance every time, but the problem still stays. I suspect that it could be caused by a circular nature of the pattern, but I'm not sure what other pattern can be used in this case.

I checked this code in both Firefox and Chrome and Chrome seems to handle it more gracefully - it purges memory after each cycle and is very fast. But the irony of the situation is that Chrome doesn't need to use this code at all. It's just an experiment to overcome Gecko 6- FormData + Blob bug (Bug 649150 - Blobs do not have a filename if sent via FormData).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半窗疏影 2024-12-07 15:47:55

试试这样:

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 将使您避免与其他读取重叠...(显然,您可以更好地修复增量,但您明白了...)

Try it like this instead:

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

The onloadend will keep you from overlapping your other reads... (Obviously, you can fix the increment a little better, but you get the idea...)

人间不值得 2024-12-07 15:47:55

Bug 已被标记为无效,因为事实证明我实际上没有正确地重新使用 FileReader 对象。

这是一个不占用内存和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,这是相关的,但不是本例中的邪恶。

感谢凯尔·休伊让我注意到这一点:)

Bug has been marked as INVALID, since it turned out that I wasn't in fact re-using FileReader object properly.

Here is a pattern, which doesn't hog memory and 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();
}

Another bug report has been filed: https://bugzilla.mozilla.org/show_bug.cgi?id=681479, which is related, but not the evil in this case.

Thanks to Kyle Huey for bringing this to my attention :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文