巨大的JavaScript HTML5 blob(来自大型ArrayBuffers),用于在客户端构建一个巨大的文件

巨大的JavaScript HTML5 blob(来自大型ArrayBuffers),用于在客户端构建一个巨大的文件,javascript,html,google-chrome,blob,html5-filesystem,Javascript,Html,Google Chrome,Blob,Html5 Filesystem,我正在编写一个web浏览器应用程序(客户端),它从许多位置下载大量块,并将它们连接起来构建一个blob。然后,该blob作为公共文件保存到本地文件系统。我这样做是通过ArrayBuffer对象和一个blob var blob=new blob([ArrayBuffer1,ArrayBuffer2,ArrayBuffer3,…],{type:mimetype}) 这适用于中小型文件(直到大约700MB),但较大文件会导致浏览器崩溃。我知道RAM内存有其局限性。情况是,我需要构建blob来生成文

我正在编写一个web浏览器应用程序(客户端),它从许多位置下载大量块,并将它们连接起来构建一个blob。然后,该blob作为公共文件保存到本地文件系统。我这样做是通过ArrayBuffer对象和一个blob


var blob=new blob([ArrayBuffer1,ArrayBuffer2,ArrayBuffer3,…],{type:mimetype})

这适用于中小型文件(直到大约700MB),但较大文件会导致浏览器崩溃。我知道RAM内存有其局限性。情况是,我需要构建blob来生成文件,但我希望允许用户下载比该大小大得多的文件(例如,想象一下,大约8GB的文件)


?我如何构建blob以避免大小限制?LocalStorage比RAM更有限,所以我不知道使用什么或如何使用。

看起来您只是将数据数组连接在一起?为什么不将阵列缓冲区添加到一个巨大的blob中呢。您必须一次迭代并追加一个arrayBuffer。您可以将
搜索
添加到filewriter的末尾以附加数组。对于只读取大blob的部分内容,您可以获得blob的
切片
,以避免浏览器崩溃

附加函数

function appendToFile(fPath,data,callback){
    fs.root.getFile(fPath, {
        create: false
    }, function(fileEntry) {
        fileEntry.createWriter(function(writer) {
            writer.onwriteend = function(e) {
                callback();
            };
            writer.seek(writer.length);
            var blob = new Blob([data]);
            writer.write(blob);
        }, errorHandler);
    }, errorHandler);
}
function getPartialBlobFromFile(fPath,start,stop,callback){
    fs.root.getFile(fPath, {
        creation:false
    }, function(fileEntry){
        fileEntry.file(function(file){
            var reader = new FileReader();
            reader.onloadend = function(evt){
                if(evt.target.readyState == FileReader.DONE){
                    callback(evt.target.result);
                }
            };
            stop = Math.min(stop,file.size);
            reader.readAsArrayBuffer(file.slice(start,stop));
        }, errorHandler)
    }, errorHandler);
}
同样,为了避免读取整个blob,在生成您提到的文件时,只读取巨型blob的部分/块

部分读取功能

function appendToFile(fPath,data,callback){
    fs.root.getFile(fPath, {
        create: false
    }, function(fileEntry) {
        fileEntry.createWriter(function(writer) {
            writer.onwriteend = function(e) {
                callback();
            };
            writer.seek(writer.length);
            var blob = new Blob([data]);
            writer.write(blob);
        }, errorHandler);
    }, errorHandler);
}
function getPartialBlobFromFile(fPath,start,stop,callback){
    fs.root.getFile(fPath, {
        creation:false
    }, function(fileEntry){
        fileEntry.file(function(file){
            var reader = new FileReader();
            reader.onloadend = function(evt){
                if(evt.target.readyState == FileReader.DONE){
                    callback(evt.target.result);
                }
            };
            stop = Math.min(stop,file.size);
            reader.readAsArrayBuffer(file.slice(start,stop));
        }, errorHandler)
    }, errorHandler);
}
你可能需要保留索引,也许是在你巨大的BLOB的标题部分-我需要知道更多,然后才能给出更精确的反馈


更新-避免配额限制,临时与持久 回应你下面的评论
您似乎遇到了存储配额问题,因为您正在使用临时存储。以下是从google found中借用的一个片段

在浏览器中运行的所有web应用程序之间共享临时存储。共享池最多可以是可用磁盘空间的一半。应用程序已使用的存储包括在共享池的计算中;也就是说,计算基于(可用存储空间+应用程序使用的存储)*.5

每个应用程序最多可以拥有20%的共享池。例如,如果总可用磁盘空间为50 GB,则共享池为25 GB,应用程序最多可以有5 GB。这是根据可用磁盘空间(50 GB)的一半(25 GB)的20%(最多5 GB)计算得出的

为了避免这个限制,您必须切换到persistent,它将允许您配额到磁盘上的可用空间。为此,请使用以下命令来初始化文件系统,而不是临时存储请求

navigator.webkitPersistentStorage.requestQuota(1024*1024*5, 
  function(gB){
  window.requestFileSystem(PERSISTENT, gB, onInitFs, errorHandler);
}, function(e){
  console.log('Error', e);
})

创建文件并尝试将所有传入的数组附加到文件中,而不仅仅是一次写入。现在我遇到了另一个问题:这会将一个文件构建到浏览器html5文件系统中,但存储空间有限(尽管我请求5GB浏览器允许我使用大约2GB),因此我遇到了比它大的文件的问题。有没有办法消除这些限制?也许,你是如何发现这个问题的?是否有抛出的错误或任何其他信息?您的硬盘/可用空间有多大?我有既得利益。最近的chrome更新(如果您使用chrome?)可能存在垃圾收集问题。我必须设置超时并重试ajax下载。回到桌面时,请告诉我我会尽力提供帮助。我通过
窗口请求5GB的临时存储。requestFileSystem()
,但如果我调用
navigator.webkitTemporaryStorage.queryUsageAndQuota()
,我可以看到我只能使用2GB(或更少的其他计算机)的临时存储。啊,好吧,你使用的是临时存储吗?您可以通过使用持久性存储来解决这个问题。临时存储只允许共享剩余未使用驱动器空间池的20%。您需要切换到持久性存储,要做到这一点,下面是我用代码编写的一个答案,关于如何实现持久性存储,持久性存储允许您使用所有未使用的磁盘空间(但用户必须接受浏览器提供的弹出式请求)