This will be possible only with a combination of a service worker + fetch + stream. Some browsers have a working and selective modes, but even less support fetching with streaming (Blink)
new Response(new ReadableStream({...}))
I created a streaming file saver library to communicate with another service worker to intercept a network request: StreamSaver.js
This is a little different from the node thread, 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') ) })
There are also two other ways to get a stream response using xhr, but it is not standard and does not matter if you use them (responseType = ms-stream || moz-chunked-arrayBuffer), because StreamSaver depends on fetch + ReadableStream by any method and cannot be used in any other way
You can do something similar later when WritableStream + Transform streams are also implemented
fetch(url).then(res => { const fileStream = streamSaver.createWriteStream('filename.txt') res.body .pipeThrogh(unencrypt) .pipeTo(fileStream) .then(done) })
It is also worth mentioning that the default download manager is usually associated with background loading, so ppl sometimes closes the tab when it sees a download. But all this happens in the main thread, so you need to warn the user when he leaves
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 }
source share