[removed] Writing to download stream

前端 未结 2 422
無奈伤痛
無奈伤痛 2020-12-17 01:02

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 wa

相关标签:
2条回答
  • 2020-12-17 01:16

    out of security reason, browsers do not allow piping incoming readablestream directly into the local file system, so u have 2 ways to solve it:

    1. window.open(Resourse_URL): download the resource in a new window with Content_Disposition set to "attachment";
    2. <a download href="path/to/resourse"></a>: using the "download" attribute of AnchorElement to download stream into the hard disk;

    hope these helps:)

    0 讨论(0)
  • 2020-12-17 01:34

    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({...}))

    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')
        )
    })
    

    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

    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
    }
    
    0 讨论(0)
提交回复
热议问题