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

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

问题描述

我想从我的服务器下载一个加密文件,解密并保存在本地.我想解密文件并在下载文件时将其写入本地,而不是等待下载完成、解密然后将解密的文件放入锚标记中.我想这样做的主要原因是,对于大文件,浏览器不必在内存中存储数百兆字节或几千兆字节.

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)

new Response(new ReadableStream({...}))

我已经构建了一个流文件保护程序库来与其他服务工作者通信以拦截网络请求: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) 因为 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 + Transform 流也被实现时,你将能够做这样的事情

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天全站免登陆