如何在不崩溃浏览器的情况下使用IndexedDB创建一个非常长的字符串?

时间:2014-11-22 19:59:05

标签: javascript indexeddb bloburls

我正在编写一个Web应用程序,它会生成一个用户将下载的潜在大文本文件,并且所有处理都在浏览器中完成。到目前为止,我能够以小块的形式读取超过1 GB的文件,处理每个块,逐步生成大量输出文件,并将增长的输出存储在IndexedDB中。我更天真的尝试将所有结果保存在内存中,然后在最后将它们序列化为文件,导致所有浏览器崩溃。

我的问题是双重的:

  1. 我可以追加到IndexedDB中的条目(字符串或数组)而不先将整个内容读入内存吗?现在,这个:

    task.dbInputWriteQueue.push(output);
    var transaction = db.transaction("files", "readwrite");
    var objectStore = transaction.objectStore("files");
    var request = objectStore.get(file.id);
    request.onsuccess = function()
    {
        request.results += nextPartOfOutput
        objectStore.put(request.results);
    };
    
    输出开始变大后,

    导致崩溃。我可以在数据库中写一堆小条目,但是后来我不得不将它们全部读入内存,以便将它们连接起来。见我的问题的第2部分......

  2. 我可以创建数据对象URL以引用IndexedDB中的值而不将该值加载到内存中吗?对于小字符串,我可以这样做:

    var url = window.URL.createObjectURL(new Blob([myString]), {type: 'text/plain'});
    

    但对于大字符串,这并不太好。实际上,它在加载字符串之前崩溃了。似乎使用来自IndexedDB的get()的大读取导致Chrome崩溃(甚至开发人员工具崩溃)。

  3. 如果我使用Blob而不是字符串会更快吗?这种转换便宜吗?

    基本上我需要一种方法,使用JavaScript,将一个非常大的文件写入磁盘,而不是在任何一点上将整个内容加载到内存中。我知道你可以给createObjectURL一个文件,但这不适用于我的情况,因为我正在从用户提供的文件中生成 new 文件。

2 个答案:

答案 0 :(得分:6)

存储Blob将使用更少的空间和资源,因为不再需要转换为base64。您甚至可以将“text / plain”对象存储为blob:

var blob = new Blob(['blob object'], {type: 'text/plain'});
var store = db.transaction(['entries'], 'readwrite').objectStore('entries');

// Store the object  
var req = store.put(blob, 'blob');
req.onerror = function(e) {
    console.log(e);
};
req.onsuccess = function(event) {
    console.log('Successfully stored a blob as Blob.');
};

您可以在此处查看更多信息: https://hacks.mozilla.org/2012/02/storing-images-and-files-in-indexeddb/

Chrome仅在2014年夏天支持此功能:http://updates.html5rocks.com/2014/07/Blob-support-for-IndexedDB-landed-on-Chrome-Dev因此您无法在旧版Chrome上使用此功能。

答案 1 :(得分:0)

我刚刚重新打开了我在2年前提交的Chrome bug并为FF team创建了另一个与创建大blob时浏览器崩溃相关的错误。生成大文件应该不是浏览器的问题。