【问题标题】:Javascript FileSaver saves empty files after writing large number of filesJavascript FileSaver在写入大量文件后保存空文件
【发布时间】:2012-07-12 21:15:17
【问题描述】:

背景

我正在开发一个基本上可以在客户端生成视频的内部项目,但由于我知道没有 JavaScript 视频编码器,所以我只是单独导出每个帧。我需要避免上传到服务器;这一切都发生在客户端。

实施

我正在使用FileSaver.js(更具体地说,Chrome 的 webkit FileSystem API)来保存由 HTML5 画布生成的大量 PNG。我将 Chrome 设置为自动下载到特定文件夹,所以当我点击“保存”时,它就会起飞并每秒保存 20 张图像。这非常适合我的目的。

如果我可以使用JSZip 将所有这些帧压缩到一个文件中,然后将其提供给客户端进行保存,我会的,但我什至没有尝试过,因为浏览器没有足够的内存来生成~8000 个 640x480 PNG,然后压缩它们。

问题

问题是在一定数量的图像之后,下载的每个文件都是空的。 Chrome 甚至开始在下载栏中告诉我该文件为 0 字节。在具有相同导出设置的同一个项目上重复,空保存在完全相同的时间开始。例如,对于一个项目,我可以在它阻塞之前保存前 5494 帧。 (我知道这是一个非常大的数字,但我无能为力。)我尝试在保存之间设置 10 毫秒的延迟,但这没有任何效果。我没有尝试更大的延迟,因为导出需要很长时间。

我检查了 blob.size 并且它永远不会为零。我怀疑它超出了一些配额,但没有抛出错误;它只是默默地无法写入沙箱或将文件复制到用户指定的位置。

问题

如何检测这些空存档?阻止他们?有一个更好的方法吗?我是不是搞砸了?


编辑:实际上,在调试 FileSaver.js 之后,我意识到它甚至没有使用 webkitRequestFileSystem;它到达这里时返回:

if (can_use_save_link) {
    object_url = get_object_url(blob);
    save_link.href = object_url;
    save_link.download = name;
    if (click(save_link)) {
        filesaver.readyState = filesaver.DONE;
        dispatch_all();
        return;
    }
}

所以,它看起来甚至没有使用 FileSystem API,因此我不知道如何在存储空间满之前清空它。


编辑 2:我尝试将“if (can_use_save_link)”块移动到“writer.onwriteend”函数内部,并将其更改为:

if (can_use_save_link) {
    save_link.href = file.toURL();
    save_link.download = name;
    click(save_link);
}else{
    target_view.location.href = file.toURL();
}

结果是我能够保存所有 8260 个文件(总共约 1.5GB),因为它现在使用具有配额的存储空间。以前,这些文件没有出现在 HTML5 文件系统中,因为我假设如果锚元素支持“下载”属性,您就不需要将它们放在那里。

我还能够注释掉将“.download”附加到文件名的代码,并且我必须为“file.remove()”的两个实例提供一个空的匿名函数作为参数。

【问题讨论】:

  • 只是为了确定 - 这 5494 个文件加起来有多大?如果您请求使用 FileSaver.js appears 的临时文件系统,则基本上只允许使用 10% 的硬盘空间。 (See here for more information.)。
  • 刚刚检查过,它们总共有 0.99GB。我的硬盘容量约为 450GB,有 339GB 可用空间。

标签: javascript file google-chrome filesystems


【解决方案1】:

使用 JSZip,如果禁用压缩(这是默认设置),它不会占用太多内存。要手动禁用压缩,请确保在调用 zip.generate() 时传递 compression: "STORE"

【讨论】:

  • 这似乎工作到目前为止,但我不知道如何使用 FileSaver 来保存生成的 .zip 文件。我现在使用的方法是生成一个无效的 zip 文件。我正在尝试使用这样的 BlobBuilder: var bb = new BlobBuilder; bb.append(app.Analysis.playback.zip.generate()); saveAs(bb.getBlob("application/zip"), app.Analysis.playback.baseFilename+'.zip');
  • 另外,我正在使用 canvas.toDataURL('image/png') 从画布生成图像,因此将它们添加到 zip 文件需要同时将所有这些 base64 编码的 PNG 保存在内存中,对?使用此方法,浏览器选项卡会在它确定已足够时崩溃。你知道更好的方法吗?
  • 试试 canvas.toBlob() 代替:github.com/eligrey/canvas-toBlob.js - 对于没有 BlobBuilder 的浏览器,你也可以试试 github.com/eligrey/BlobBuilder.js
【解决方案2】:

我最终修改了 FileSaver.js(参见原帖中的“EDIT 2”)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多