上传和操作多个文件时的内存使用率很高

问题描述:

我想使用FineUploader来上传大量文件。我还需要在上传文件之前操作这些文件 - 即我需要匿名一些识别信息。在another answer中,Ray Nicholus建议在onSubmit处理程序中拒绝原始文件,然后重新添加操作文件。所以我的onSubmit处理程序看起来像这样:上传和操作多个文件时的内存使用率很高

onSubmit: function (id, name) 
{ 
    var file = this.getFile(id) 
    if (file.isAnonymized) 
    { 
     return; 
    } 
    var reader = new FileReader() 
    reader.onload = function() 
    { 
     var arrayBuffer = this.result 
     var byteArray = new Uint8Array(arrayBuffer) 
     // Manipulate the byteArray in some way... 
     var blob = new window.Blob([byteArray]) 
     blob.isAnonymized = true 
     // add the anonymized file instead 
     uploader.addFiles({blob: blob, name: name}) 
    } 
    reader.readAsArrayBuffer(file) 
    // cancel the original file 
    return false 
}, 

这适用于少量的文件。在一个具体的例子中,一位客户试图在Firefox中上传〜1.500个3MB的文件,并且在标签最终崩溃之前看到Firefox的内存使用率高涨。其他浏览器(Chrome,Edge)表现出类似的行为。使用浏览器的开发人员工具似乎没有显示任何大的内存分配。按原样上传文件时没有问题,但这不是一个选项。

+0

您可能会考虑以某种方式将其放入WebWorker中。 – TryingToImprove

+0

某些js文件库不是用来管理大量文件的。 XMLHttpRequest是巨大的异步对象。通常情况下,当你放入超过1000个文件时(因为它分配并尝试启动1000个同时连接),这种类型库会在for循环中启动所有上传操作,挂起浏览器。我建议你写自己的上传部分。 – Fefux

+0

就像我说过的,只是上传作品就像一个魅力,所以我很有信心,这不是问题。这是当我需要事先处理文件时,疼痛开始。 –

我在https://github.com/sgarcialaguna-mms/file-upload-memory/的某处清理了一下这个例子,现在我确信这个错误是由于fineuploader库持有blob超过需要的时间。

该示例现在一次将一个文件加载到内存中,然后将blob传递到上传库。我现在也使用实际的服务器(来自fineuploader服务器示例存储库的Django示例)。

使用Firefox时,当我拖入大约1GB的文件时,即使上传完成后,Firefox的内存使用量也会在上传过程中稳步上升并保持在较高水平。我可以打开about:memory,点击“Minimize memory usage”触发垃圾回收,按下“Measure”,文件数据显示在“memory-file-data/large”下。调用​​,再次触发垃圾回收,Firefox的内存使用量急剧下降。再次测量显示“内存文件数据/大”对象不再存在于内存中。根据https://github.com/FineUploader/fine-uploader/issues/1540#issuecomment-194201646,每次上传后都会调用this._handler.expunge(id)

Chrome的行为有点不同,由于长期存在的bug,一旦超过500 MB的blob数据累积,它最终开始抛出ERR_FILE_NOT_FOUND错误。 chrome:// blob-internals页面显示哪些blob正在被保存以及它们的refcount。

我不知道是否有一个简单的方法来告诉哪些变量/闭包/任何持有这些对象,但它会非常有帮助。

+0

文件不占用内存,它们由磁盘支持。保持这些文件不会消耗内存。但是,如果您传递的Blob不受磁盘上的文件支持,则这是一个不同的故事。我不知道任何Fine Uploader将会持续超过必要时间的区域。为了确信情况是这样的,需要探索代码,并且需要揭示问题出现的位置。 –

+0

最有可能的问题在于你的代码。如果将1 GB内存支持的Blob传递给Fine Uploader,当然这会消耗1 GB的内存,并且Blob必须保持在范围内直到它们被上传。 –

+0

好吧,我最后的评论,因为我将在今年剩余时间内无法上网。 @ RayNicholus“最有可能的问题出现在你的代码中,如果你将1GB内存支持的Blob传递给Fine Uploader,当然这会消耗1GB内存,并且Blob必须保留在范围内已上传“。这很明显。正如我明确指出的那样,问题在于上传后内存不会被释放。 “很可能,问题出在您的代码中。”我的代码就在那里。它几乎只有60行。如果你能发现我犯的错误,我会很乐意听到它。 –