jimmywarting / StreamSaver.js

StreamSaver writes stream to the filesystem directly asynchronous
https://jimmywarting.github.io/StreamSaver.js/example.html
MIT License
4.04k stars 418 forks source link

Pause and Resume download #159

Closed Akayeshmantha closed 4 years ago

Akayeshmantha commented 4 years ago

Hi @jimmywarting is it possible to pause and resume the readbleStream or writablestream when performing the download.

Btw I saw in node.js readable stream has a function to pause but I don't see them in the web api's readbleStream and writablestream any idea how to achieve this?

jimmywarting commented 4 years ago

hmm, well, I don't think there isn't anything similar to node's pause/resume functionality in whatwg streams, however you can control it in some ways by controlling how you write/enqueue chunks

believe this question is best asked here https://github.com/whatwg/streams/issues or on stackoverflow

readbleStream or writablestream when performing the download.

Guessing you are using both, with fetch? you could get both the reader and the writer and read the stream manually and pass it along.

Some basic idea:

var res = await fetch(...)
var reader = res.body.getReader()
var writer = new WritableStream().getWriter()

while (not_paused) {
  chunk = await reader.read()
  if (chunk.done) return
  writer.write(chunk.value)
}

a stream can also "paused" if something is async


var pipe = new TransformStream({
  async transform(chunk, ctrl) {
    if (paused) await some_promise_waiting_to_resume
    ctrl.enqueue(chunk)
  } 
})
res.body
  .pipeThrough(pipe)
  .pipeTo(writable_stream)
``´
Akayeshmantha commented 4 years ago

Hi @jimmywarting

Thanks alot for the response um actually the reading part I was able to pause but is it possible to pause the write stream as well it's I think getting closed cant write back to the same stream when we pause the reading stream ? means the download process not getting pause in the browser it's getting stopped.

     $pause.onclick = () => {
        if(!pause){
          pause = true;

        }else{
          pause = false;
          pauseRes();
        }

       }

       $start.onclick = () => {
          const url = 'http://localhost:8081/downloadFile'
          const fileStream = streamSaver.createWriteStream('aka.pdf')
          fetch(url,{signal: abortSignal})
              .then(resp => {
                  return resp.body;
              })
              .then(res => {
                  updateProgress(res)
              })

        }

        function pauseRes(){
          if(!pause){
            Promise.resolve(true);
          }
        }

        async function updateProgress(res){
          const fileStream = streamSaver.createWriteStream('aka.pdf')
                var progress = new TransformStream({
                   async transform(chunk, controller) {
                      if(!pause){
                          await pauseRes();
                          controller.enqueue(chunk);
                      }            
                  }
                })
                const readableStream = res;
                rstream = readableStream;
              // more optimized
                if(window.WritableStream && readableStream.pipeTo){
                    return readableStream
                    .pipeThrough(progress)
                    .pipeTo(fileStream,{signal: abortSignal})
                      .then(() => console.log('done writing'))
                }
        }
Akayeshmantha commented 4 years ago

Hi @jimmywarting

Is there any contoller like abortcontroller which can signal to pause the downlod in the browser ?

jimmywarting commented 4 years ago

Is there any contoller like abortcontroller which can signal to pause the downlod in the browser ?

To the native browser UI, No there isn't. The reverse could work with a bit of hack doe. you can kinda figure out if the client pause the download from the native UI if the pull function isn't called or if the underlying bucket's desired size never decreases. but for that you kinda need support for transferable streams

Akayeshmantha commented 4 years ago

Sure thanks @jimmywarting

Btw why do we have mitm: 'https://jimmywarting.github.io/StreamSaver.js/mitm.html?version=2.0.0'

When downloading from firefox I have open dev tools to start the download for the first time. Is there a workaround for this

jimmywarting commented 4 years ago

mitm is used so that you don't have to set up a service worker and it can work directly from npm and insecure sites.

it seems like FF have a bug with self.clients.claim() or something like that.