我正在编写一个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
一个文件,但这不适用于我的情况,因为我正在从用户提供的文件中生成 new 文件。
答案 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时浏览器崩溃相关的错误。生成大文件应该不是浏览器的问题。