JavaScript:写入下载流

JavaScript:写入下载流,javascript,encryption,download,file-storage,Javascript,Encryption,Download,File Storage,我想从我的服务器下载一个加密文件,解密并保存在本地。我想解密文件并在下载时本地写入,而不是等待下载完成,解密后将解密后的文件放入锚标记中。我想这样做的主要原因是,对于大文件,浏览器不必在内存中存储数百兆字节或数千兆字节 这只有通过服务工作者+获取+流的组合才能实现 少数浏览器具有worker和fetch,但支持流式提取的浏览器更少(闪烁) newresponse(newreadablestream({…})) 我构建了一个流文件保护程序库,用于与其他服务器中的服务人员通信,以拦截网络请求: 它和

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

这只有通过服务工作者+获取+流的组合才能实现 少数浏览器具有worker和fetch,但支持流式提取的浏览器更少(闪烁)

newresponse(newreadablestream({…}))

我构建了一个流文件保护程序库,用于与其他服务器中的服务人员通信,以拦截网络请求:

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

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,不能以任何其他方式使用

稍后,当WritableStream+Transform streams也得到实现时,您将能够执行类似的操作

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

    res.body
        .pipeThrogh(unencrypt)
        .pipeTo(fileStream)
        .then(done)
})
还值得一提的是,默认下载管理器通常与后台下载相关联,因此ppl有时会在看到下载时关闭选项卡。但这一切都发生在主线程中,因此您需要在用户离开时警告他们

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
}

出于安全原因,浏览器不允许将传入的readablestream直接传输到本地文件系统,因此您有两种解决方法:

  • 窗口。打开(资源库URL)
    :使用 内容\u处置设置为“附件”
  • :使用 将流下载到硬盘中的锚元素
    希望这些帮助:)

    您有数据解密算法吗?我计划使用AES。您不能用浏览器Javascript在用户计算机上写入文件。因此,除非您使用电子或类似的工具,否则您无法完成您试图实现的目标。@LukePark“您无法使用浏览器Javascript在用户计算机上写入文件。”从技术上讲,可以写入用户文件系统。使用所描述的方法如何?是否可以在下载内容时对其进行编辑?是否缺少未加密方法的实现?是的,因为未加密可以不同的方式工作,请查看WebCrypt是否实现您自己的解密嗨,我使用angular,我尝试了相同的解决方案,即使我在控制台上没有看到任何错误,我也无法获得下载弹出窗口。我可以在stream中下载,这是它的救星,多亏了在客户端使用StreamSaver JS来流式传输数据。正在下载的文件已加密,数据为base64格式。从fetch返回的流数据位于Uint8Array中。有没有办法改变它的字符串格式?我问的原因是,一旦数据是Unit8Array格式,当数据涉及多字节字符时,我发现很难从Unit8Array获取字符串(bas64编码的数据)