jimmywarting / StreamSaver.js

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

Files downloaded from server using content-disposition attachment and with specified size not showing native progress #260

Open lifter035 opened 2 years ago

lifter035 commented 2 years ago

So we have following in and download works but there's no native progress in any browser (browser shows standard download process only at the end of download):

const response = await fetch(downloadUrl, {
  headers: { Authorization: authHeader }
})
const fileStream = streamSaver.createWriteStream(file.name, {
  size: file.size
})
response.body.pipeTo(fileStream)

If we use

response.body.pipeTrough(progress).pipeTo(fileStream)

and log bytes in progress TransformStream we see progress alright.

Any ideas? Thanks

jimmywarting commented 2 years ago

Hmm, weird. it works for me in chrome. maybe take a look at the network request and try to see if the download url attach any content-length header


If you have control over the server and how files are downloaded, then i recommend to use it to save files instead of trying to emulate it with a service worker.

responding with a content-disposition attachment is pretty useless when it's behind a demanding request header that isn't a cookie (that is sent in every request)

Any use of Authorization header or api key in the header will make it impossible to download something using browsers default behavior.

May i suggest that you try to download the file in any other way that don't require a Authorization header? there are plenty of options

as long as you can trigger browsers default navigation to a file with a content-disposition attachment header then that will be your best solution.

lifter035 commented 2 years ago

Yeah it's weird not sure why, server responds with correct headers and we have file.name and file.size already available from file metadata before fetch response. Part of response headers:

content-disposition: attachment; filename="test.mp4";filename*=UTF-8''test.mp4
content-language: en-US
content-length: 4823255
content-type: video/mp4

It works ok if we append token as url param and use just window.open with url. But for security reasons we want to switch to auth header for now until backend can be updated

JamesUgbanu commented 2 years ago

I am also having similar issue with Safari 15.2. The problem is I can only see the progress on the network tab and only shows when the download is complete.

jimmywarting commented 2 years ago

safari don't support downloading content generated by the service worker so it use a other technic it concat all chunks into one blob and saves it using <a href="${URL.createObjectURL(file)}" download="name"> instead

see https://github.com/jimmywarting/StreamSaver.js/issues/69

JamesUgbanu commented 2 years ago

@jimmywarting Thanks for the wonderful package. Which other method do you think I can use to resolve this issue on safari?

jimmywarting commented 2 years ago

@JamesUgbanu Safari is just really only limited to <a download> and blob urls unfortunately

I keep recommending to everyone that the use of you own backend/server is the best corse of action for saving remote files whenever possible.

FileSaver, StreamSaver and file system access is main targeted focus group is for folks who generate data on the client side where data isn't stored on a server and you have no other options.

DemonICOLI commented 2 years ago

I'm Having this exact same issue on Firefox and Chrome while deployed on the server, not on localhost.

I can see the progress on the network tab, but the native download only starts once the fetch finishes, and it is not being piped to Stream saver

reinos commented 2 years ago

Same here, it fetch the data but the download started after the data has been fetched.

jimmywarting commented 2 years ago

i know that in chrome at least you need to write at least some few bytes for it to start, but not that you have to write the hole thing

reinos commented 2 years ago

Thanks for your your reply @jimmywarting. The issue for me is that im using Safari. It seems that Safari has some issues with this lib. https://github.com/jimmywarting/StreamSaver.js/issues/69

jimmywarting commented 2 years ago

ah, i see. well safari is a total other ball game. I'm still unsure if safari have added support yet. last time i tried it could not save a file that was generated by a service worker. It would just abort the request and re-make the request in another download manager thread and totally circumvent the service worker, giving you a 404 file instead.

that's why i had to generate a Blob and save the data instead.

Safari has all the tools that are needed by streamsaver. but dose something weird when it encounter a download. so detecting feature support is a bit hard.

I think there have been some recent advancement in safari that allows us to download files with service worker now days. haven't tested it doe..