JavaScript:写下载流 [英] JavaScript: Writing to download stream

查看:317
本文介绍了JavaScript:写下载流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从我的服务器下载一个加密的文件,将其解密并在本地保存。我想解密该文件,并在本地下载它,而不是等待下载完成,解密,然后将解密的文件放在锚标签中。我想这样做的主要原因是,使用大文件,浏览器不必在内存中存储数百兆字节或几GB。

I want to download an encrypted file from my server, decrypt it and save it locally. I want to decrypt the file and write it locally as it is being downloaded rather than waiting for the download to finish, decrypting it and then putting the decrypted file in an anchor tag. The main reason I want to do this is so that with large files the browser does not have to store hundreds of megabytes or several gigabytes in memory.

推荐答案

只有使用service worker + fetch + stream
的组合才有可能几个浏览器工作人员和获取,但支持使用流式传输(Blink)支持更少的支持

This is only going to be possible with a combination of service worker + fetch + stream A few browser has worker and fetch but even fewer support fetch with streaming (Blink)

新的响应(新的ReadableStream({...}))

我已经构建了一个流文件保护程序lib,与其他服务工作者进行通信,以拦截网络请求: StreamSaver.js

I have built a streaming file saver lib to communicate with a service worker in other to intercept network request: StreamSaver.js

与节点的流有点不同,这里是一个例子

It's a little bit different from node's stream here is an example

function unencrypt(){
    // should return Uint8Array
    return new Uint8Array()
}

// We use fetch instead of xhr that has streaming support
fetch(url).then(res => {
    // create a writable stream + intercept a network response
    const fileStream = streamSaver.createWriteStream('filename.txt')
    const writer = fileStream.getWriter()

    // stream the response
    const reader = res.body.getReader()
    const pump = () => reader.read()
        .then(({ value, done }) => {
            let chunk = unencrypt(value)

            // Write one chunk, then get the next one
            writer.write(chunk) // returns a promise

            // While the write stream can handle the watermark,
            // read more data
            return writer.ready.then(pump)
        )

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

还有另外两种方法可以使用xhr获得流式响应,但是它不是标准的,如果你使用它们不受影响(responseType = ms-stream || moz-chunked-arrayBuffer)cuz StreamSaver依赖于fetch + ReadableStream,不能以任何其他方式使用

There are also two other way you can get streaming response with xhr, but it's not standard and doesn't mather if you use them (responseType = ms-stream || moz-chunked-arrayBuffer) cuz StreamSaver depends on fetch + ReadableStream any ways and can't be used in any other way

稍后,当WritableStream +变换流也实现时,您将能够执行此操作

Later you will be able to do something like this when WritableStream + Transform streams gets implemented as well

fetch(url).then(res => {
    const fileStream = streamSaver.createWriteStream('filename.txt')

    res.body
        .pipeThrogh(unencrypt)
        .pipeTo(fileStream)
        .then(done)
})

还值得一提的是,默认的下载管理器通常与后台下载相关联,因此当有人看到下载时,有时关闭该选项卡。但是这主要发生在主线程中,所以您需要在用户离开时提醒用户。

It's also worth mentioning that the default download manager is commonly associated with background download so ppl sometimes close the tab when they see the download. But this is all happening in the main thread so you need to warn the user when they leave

window.onbeforeunload = function(e) {
  if( download_is_done() ) return

  var dialogText = 'Download is not finish, leaving the page will abort the download'
  e.returnValue = dialogText
  return dialogText
}

这篇关于JavaScript:写下载流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆