Closed jat255 closed 4 years ago
@jimmywarting sorry to bug, but any thoughts on this issue?
// don't
ws = new WritableStream()
writer = ws.getWriter() // locks the stream
ws.abort() // Failed to execute 'abort' on 'WritableStream': Cannot abort a locked stream
// do
ws = new WritableStream()
writer = ws.getWriter() // locks the stream
writer.abort()
// or
ws = new WritableStream()
writer = ws.getWriter() // locks the stream
writer.releaseLock() // releases the lock
ws.abort()
as for the browser ui when they cancel, it don't properly propegate back to the service worker when it's aborted. so yea, it's related to #13
if you provide them with a abort button then you could perhaps cancel both the fetch and the writeable stream with AbortController/AbortSignal
other (perhaps easier) solution could have you tried just using a link <a download="filename" href="url">download</a>
instead of emulating what a server dose with streamsaver, just provide a content-disposition attachment response header from the backend.
Thanks! Can I still use this approach with pipeTo
/pipeThrough
? It appears those methods use the streams directly, rather than the writers/readers, but perhaps I'm misunderstanding.
I'm doing some individual file downloading this way (which I could do directly in the browser as you mention), but since I'm also using zip-stream.js
, I wanted to do it all the same way so I could have one progress bar for all the downloads (regardless of if they're individual files or in a zip).
I'm doing the following for the zips, but I'm not sure where I would use the getWriter()
in this example:
let writeStream = streamSaver.createWriteStream(
zip_title,
{ size: total_bytes});
z = new ZIP({
pull (ctrl) {
const it = files.next()
if (it.done) {
ctrl.close()
} else {
const [name, url] = it.value
return fetch(url).then(res => {
ctrl.enqueue({
name,
stream: () => {
r = res.body;
return r
}
});
})
}
}}).pipeThrough(progressStream)
.pipeTo(writeStream)
.catch( err => {
console.log('failed to save zip');
errorProgress();
showError('something went wrong');
});
EDIT: I'll look more into AbortController/AbortSignal... That looks like it might be what I need.
Fantastic! AbortController was exactly what I needed. MWE for those coming to this later:
var abortController = new AbortController();
var abortSignal = abortController.signal;
z = new ZIP({
pull (ctrl) {
const it = files.next()
if (it.done) {
ctrl.close()
} else {
const [name, url] = it.value
return fetch(url,
{signal: abortSignal})
.then(res => {
ctrl.enqueue({
name,
stream: () => {
r = res.body;
return r
}
});
})
}
}
}).pipeThrough(progressTransform)
.pipeTo(writeStream,
{signal: abortSignal})
.catch( err => {
if (abortSignal.aborted) {
console.log('User clicked cancel');
} else {
console.log('There was an error during the download:', err.message);
}
});
An example of this might be good to add to the docs somewhere (maybe this is obvious to an actual JS developer, but as a hacker this took me a while to figure out).
I am not really a javascript developer, so forgive me if I'm missing something obvious, but I'm having trouble creating a button that will cancel an in-progress download using StreamSaver.
My application is using
StreamSaver.js
,zip-stream.js
, andweb-streams-polyfill
(to provide pipes and TranformStreams in Firefox) andweb-streams-adapter
(to allow use of pipes on a Fetch API call in Firefox). I have different download functions for zipping files and then for some single large files, and neither can be canceled due to locked writers. Specifically, the error I get when attempting to usewriteStream.abort()
isPromise {<rejected>: TypeError: Failed to execute 'abort' on 'WritableStream': Cannot abort a locked stream
. I'm using aTransformStream
to accumulate the number of bytes downloaded to update a progress bar.The code is basically this (for downloading a single large file):
I've attached an event handler to a cancel button that tries to call
fileStream.abort()
, but then this gives an error because the stream is locked. Am I doing something wrong, or is this not possible? When canceling the download from the browser, the actual download still continues (I think this is #13), so I was hoping to provide a means for the users to cancel the download (currently the only thing that works is refreshing or closing the page.