如何使用 IndexedDB 制作一个非常长的字符串而不会使浏览器崩溃?

Posted

技术标签:

【中文标题】如何使用 IndexedDB 制作一个非常长的字符串而不会使浏览器崩溃?【英文标题】:How can I make a really long string using IndexedDB without crashing the browser? 【发布时间】:2015-01-20 19:24:44 【问题描述】:

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

我的问题有两个:

    我可以在不先将整个内容读入内存的情况下附加到 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 部分...

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

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

    但是对于大字符串,这不太好。事实上,它在加载字符串之前就崩溃了。似乎使用 IndexedDB 中的get() 进行大量读取至少会导致 Chrome 崩溃(甚至开发人员工具也会崩溃)。

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

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

【问题讨论】:

不推荐使用文件系统 API(在发布之前已弃用)? 嗨,马特,恐怕这只能使用 chrome 上的文件系统 API,我已经实现了这样的解决方案,我能够创建高达 4GB 的文件,其他解决方案是发送数据到服务器并在那里创建文件。在他们将写入函数添加到文件 API 之前,这在浏览器中是不可能的。 正如@DeniSpasovski 建议的那样,尝试“将数据发送到服务器并在那里创建文件”。另外,发布它,而不是使用GET,因为POST 允许发送比GET 更多的数据。 如果您的目标只是桌面浏览器,则可能是另一个方向 - 使用 swf 生成文件 - ***.com/questions/8150516/… @AgiHammerthief 是的 .. 我要等待 1-4Gb 上传; 【参考方案1】:

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

【讨论】:

【参考方案2】:

存储 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 上使用此功能。

【讨论】:

在存储大约 1Gb 的数据后,将文件存储在 blob 中。 我认为直到现在,您不能将要下载的文件放在js中而不将它们加载到内存中。无论如何它都会崩溃 可以使用文件存储,但该 API 仅在 Chrome 上可用

以上是关于如何使用 IndexedDB 制作一个非常长的字符串而不会使浏览器崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

魔兽世界技能宏如何制作```

我应该只使用IndexedDB还是同时使用IndexedDB和chrome.storage?

wordwrap 一个很长的字符串

对于非常长的字符串列表,啥是合适的搜索/检索方法?

实现图片本地化 ServiceWorker + IndexedDB

实现图片本地化 ServiceWorker + IndexedDB