StreamSaver.js takes a different approach. Instead of saving data in client-side storage or in memory you could now actually create a writable stream directly to the file system (I'm not talking about chromes sandboxed file system)
StreamSaver.js is the solution to saving streams on the client-side. It is perfect for webapps that need to save really large amounts of data created on the client-side, where the RAM is really limited, like on mobile devices.
|IE||No||Everything (IE is dead)|
- Chrome don't show that the file is being download and won't give you a dialog to choose where to save it until you have written at least 1024 bytes or so (think headers are included)... Or until you close the stream
But that only applies when you have the "ask where to save each time" turned on in your browser settings
- Chrome was capable of writing more than 15 GB of data without any memory issues
It's important to test browser support before you include the web stream polyfill
because the serviceWorker needs to respondWith a native version of the ReadableStream
<!-- load before streams polyfill to detect support -->
// If you know what the size is going to be then you can specify// that as 2nd arguments and it will use that as Content-Length headerconst fileStream = streamSaverconst writer = fileStream// WriteStream is a whatwg standard writable stream//// and the write fn only accepts uint8arraywriter// when you are done: you close itwriter// when you want to cancel the download: you abortwriter // ATM Canary only recognize if the stream has been errored// it's also possible to pipe a readableStream stream to the fileStream// but then you shouldn't call .getWriter() or .close()readableStream
That is pretty much all StreamSaver.js does :)
Writing some plain text
const fileStream = streamSaverconst writer = fileStreamconst encoder =let data = 'a'let uint8array = encoderwriterwriter
const fileStream = streamSaverconst blob = 'a' // 1*5 MBblob
Save a media stream
Get a "stream" from ajax
res.body is a readableByteStream, but don't have pipeTo yet
So we have to use the reader instead which is the underlying method in streams
Here is an online demo with adding ID3 tag to mp3 file on the fly: egoroof.ru/browser-id3-writer/stream
const client =const torrentId = 'magnet:?xt=urn:btih:6a9759bffd5c0af65319979fb7832189f4f3c35d&dn=sintel.mp4&tr=wss%3A%2F%2Ftracker.btorrent.xyz&tr=wss%3A%2F%2Ftracker.fastcast.nz&tr=wss%3A%2F%2Ftracker.openwebtorrent.com&tr=wss%3A%2F%2Ftracker.webtorrent.io&ws=https%3A%2F%2Fwebtorrent.io%2Ftorrents%2Fsintel-1024-surround.mp4'// Sintel, a free, Creative Commons movieclient
How is this possible?
There is not any magical saveAs() function that saves a stream, file or blob. The way we mostly save Blobs/Files today is with the help of a[download] attribute FileSaver.js takes advantage of this and create a convenient saveAs(blob, filename) function, very fantastic, but you can't create a objectUrl from a stream and attach it to a link...
link = documentlinkhref = URL // DOES NOT WORKlinkdownload = 'filename'link // Save
So the one and only other solution is to do what the server does: Send a stream with Content-Disposition header to tell the browser to save the file. But we don't have a server! So the only solution is to create a service worker that can intercept links and use respondWith() This will scream high restriction just by mentioning service worker. It's such a powerful tool that it need to run on https but there is a workaround for http sites: popups + 3rd party https site. Who would have guess that? But I won't go into details on how that works. (The idea is to use a middle man to send a dataChannel from http to a serviceWorker that runs on https).
So it all boils down to using serviceWorker, MessageChannel, postMessage, fetch, respondWith, iframes, popups (for http -> https -> serviceWorker), Response and also WritableStream for convenience and backpressure
# A simple php or python server is enoughphp -S localhost:3001python -m SimpleHTTPServer 3001# then open localhost:3001/example.html
Go ahead and vote for how important this feature is