我想从我的服务器下载加密文件,解密并在本地保存。我想解密文件并在下载时将其写入本地,而不是等待下载完成,解密,然后将解密文件放在锚标记中。我想这样做的主要原因是,对于大文件,浏览器不必在内存中存储数百兆字节或几千兆字节。
答案 0 :(得分:5)
只有服务工作者+获取+流的组合才能实现这一点 一些浏览器具有工作和获取功能,但使用流式传输支持获取更少(Blink)
new Response(new ReadableStream({...}))
我已经构建了一个流文件保护程序库lib来与其他服务工作者进行通信以拦截网络请求:StreamSaver.js
这与节点的流有点不同,这里是一个例子
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,不能以任何其他方式使用
稍后,当WriteableStream + Transform流也被实现时,你将能够做到这样的事情
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
}
答案 1 :(得分:-1)
出于安全原因,浏览器不允许将传入的可读流直接传递到本地文件系统中,因此您有两种解决方法:
window.open(Resourse_URL)
:使用以下命令在新窗口中下载资源:
Content_Disposition设置为“附件”; <a download href="path/to/resourse"></a>
:使用以下项的“下载”属性
AnchorElement将流下载到硬盘上; 希望这些帮助:)