使用PhoneGap FileWriter.write写入“大”文件

15

我的PhoneGap应用程序有问题。我想写一个15 MB的文件。如果我尝试,操作系统会占用越来越多的内存,并且应用程序会崩溃而没有消息提示。我可以在Android和黑莓平板电脑上重现这个问题。有没有一种更有效的实现写入的方法?

最好的问候

fe.createWriter(
(fw: any) => {
    fw.onwriteend = (e) => {
        fw.onwriteend = (e) => {
            callback();
        }
        fw.write(data);
    }

    // write BOM (dead for now)
    fw.write("");
},
(error: any) => {
    alert("FileWriter Failed: " + error.code);
});

这是TypeScript,我希望JS开发者不会为此而苦恼 ;)


你要把数据写到哪里?数据从哪里来?如果你要向服务器发送文件或从服务器获取文件,你可能需要查看FileTransfer - Jamie Starke
数据来自数据库(WebSQL),我想将它们写入设备上的文件。这是一种备份机制。 - 4Str4ngeG4me
2个回答

22

我找到了答案。

崩溃原因: PhoneGap FileWrite.write无法处理过大的缓冲区,不知道确切的大小,我认为这个问题是由于PG通过URL Scheme将数据传输到iOS时出现的,并且当“URL”太长时会导致崩溃。

如何修复:每次写入小块,以下是代码:

function gotFileWriter(writer) {
  function writeFinish() {
    // ... your done code here...
  }

  var written = 0;
  var BLOCK_SIZE = 1*1024*1024; // write 1M every time of write
  function writeNext(cbFinish) {
    var sz = Math.min(BLOCK_SIZE, data.byteLength - written);
    var sub = data.slice(written, written+sz);
    writer.write(sub);
    written += sz;
    writer.onwrite = function(evt) {
      if (written < data.byteLength)
        writeNext(cbFinish);
      else
        cbFinish();
    };
  }
  writeNext(writeFinish);
}

2014年8月12日更新:

在我的实践中,通过Cordova FileSystem保存文件的性能不佳,特别是对于手机上的大型文件(>5M),需要几秒钟时间。如果您正在从服务器下载文件到本地磁盘,则可能希望找到一种“高效而直接”的方式,请尝试cordova-plugin-file-transfer插件。


谢谢@Imskull。它解决了我在Android上的同样问题。 - duckegg
@Imskull:谢谢你提供的信息,有关于编写大文件(>5M)的文档链接吗? - Shankar
如果数据是一个二进制大对象(blob),你需要将“.byteLength”替换为“.size”。 - Sjoerd Pottuit
2
@lmskull 很遗憾,FileTransfer插件不支持post数据。比如你要下载一个受保护的文件,并想发送用户登录信息以进行验证,但FileTransfer不支持这样做。在我的情况下,我找不到其他解决方案,只能使用FileWriter。 - Ayman Abdel-Rahman

8

@Imskull的答案是正确的...我只是想补充关于Blob的内容(确保它是Blob而不是ArrayBuffer),这是基于上面那个的更新...我还添加了一行来确保我正在将其添加到文件末尾...这足以使您的应用程序停止崩溃(主要是在iOS上:P)

function gotFileWriter(writer) {
  function writeFinish() {
    // ... your done code here...
  }

  var written = 0;
  var BLOCK_SIZE = 1*1024*1024; // write 1M every time of write
  function writeNext(cbFinish) {
    writer.onwrite = function(evt) {
      if (written < data.size)
        writeNext(cbFinish);
      else
        cbFinish();
    };
    if (written) writer.seek(writer.length);
    writer.write(data.slice(written, written + Math.min(BLOCK_SIZE, data.size - written)));
    written += Math.min(BLOCK_SIZE, data.size - written);
  }
  writeNext(writeFinish);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接