Javascript中的大blob文件

Gab*_*jos 10 javascript firefox large-files

我有一个下载1GB文件的XHR对象.

function getFile(callback)
{
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        if (xhr.status == 200) {
            callback.apply(xhr);
        }else{
            console.log("Request error: " + xhr.statusText);
        }
    };

    xhr.open('GET', 'download', true);
    xhr.onprogress = updateProgress;
    xhr.responseType = "arraybuffer";
    xhr.send();
}
Run Code Online (Sandbox Code Playgroud)

但File API无法将所有内容加载到内存中,即使是从内存中抛出的工作者......

btn.addEventListener('click', function() {
    getFile(function() {
        var worker = new Worker("js/saving.worker.js");
        worker.onmessage = function(e) {
            saveAs(e.data); // FileSaver.js it creates URL from blob... but its too large
        };

        worker.postMessage(this.response);
    });
});
Run Code Online (Sandbox Code Playgroud)

网络工作者

onmessage = function (e) {
    var view  = new DataView(e.data, 0);
    var file = new File([view], 'file.zip', {type: "application/zip"});
    postMessage('file');
};
Run Code Online (Sandbox Code Playgroud)

我不是要压缩文件,这个文件已经从服务器压缩了.

我想首先将它存储在indexedDB上,但我还是必须加载blob或文件,即使我按范围字节请求,很快或者很晚我将不得不构建这个巨大的blob ..

我想创建blob:url并在浏览器下载后将其发送给用户

我将使用FileSystem API for Google Chrome,但我想为firefox制作一些内容,我查看了File Handle Api,但没有...

我是否必须为firefox构建扩展,以便像FileSystem一样为google chrome做同样的事情?


Ubuntu 32位

End*_*ess 6

使用ajax加载1gb +不方便仅用于监视下载进度和填充内存.

相反,我只是发送带有Content-Disposition标题的文件来保存文件.


然而,有办法绕过它来监控进展.选项一是有一个第二个websocket,它指示你在正常下载获取请求时已经下载了多少.另一个选项将在后面的底部描述


我知道你谈过在对话中使用Blinks沙盒文件系统.但它有一些缺点.如果使用持久存储,可能需要权限.它只允许剩余20%的可用磁盘.如果chrome需要释放一些空间,那么它将丢弃最后用于最新文件的任何其他域临时存储.除此之外它不能在私人模式下工作.
更不用说它一直在放弃对它的支持,并且可能永远不会在其他浏览器中结束 - 但它们很可能不会删除它,因为很多站点仍然依赖它


处理这个大文件的唯一方法是使用流.这就是我创建StreamSaver的原因.这只能在Blink(chrome&opera)ATM中使用,但最终将得到其他浏览器的支持,并将whatwg规范备份为标准.

fetch(url).then(res => {
    // One idea is to get the filename from Content-Disposition header...
    const size = ~~res.headers.get('Content-Length')
    const fileStream = streamSaver.createWriteStream('filename.zip', size)
    const writeStream = fileStream.getWriter()
    // Later you will be able to just simply do
    // res.body.pipeTo(fileStream)
    // instead of pumping

    const reader = res.body.getReader()
    const pump = () => reader.read()
        .then(({ value, done }) => {
            // here you know how large the value (chunk) is and you can
            // figure out the download speed/progress when comparing it to the size

            return done 
                ? writeStream.close()
                : writeStream.write(value).then(pump)
        )

    // Start the reader
    pump().then(() =>
        console.log('Closed the stream, Done writing')
    )
})
Run Code Online (Sandbox Code Playgroud)

这不会占用任何记忆


End*_*ess 6

我有一个理论,就是如果将文件分成多个块并存储在indexedDB中,然后再将它们合并在一起,它将起作用

Blob不是由数据组成的……更像是指向可以从中读取文件的指针 在此处输入图片说明

这意味着如果将它们存储在indexedDB中,然后执行类似的操作(使用FileSaver或替代方法)

finalBlob = new Blob([blob_A_fromDB, blob_B_fromDB])
saveAs(finalBlob, 'filename.zip')
Run Code Online (Sandbox Code Playgroud)

但是我无法确认,因为我还没有测试过,如果其他人可以