Open jimmywarting opened 5 years ago
I played with it a bit in chrome canary.
when trying out chooseFileSystemEntries({type:'saveFile'})
Tada: https://github.com/jimmywarting/native-file-system-adapter
We offer a similar library: browser-nativefs. Its API deliberately differs from the native API.
Do you have plans on adding Native File System API support to StreamSaver.js? If so, happy to help.
Saw you lib after i uploaded my adapter to the public yours is more like a shim than a polyfill or ponyfill (but without the sandboxing features)
Do you want to cross references similar projects for publicity? :)
I have had plans on adding native fs to streamsaver if only it where possible to include a file name https://github.com/WICG/native-file-system/issues/80 but it isn't so i rather prefer the current method of using content-disposition + service worker solution for a better user experience. It will also allow things such as auto download on user interaction without prompting. and show a native progress indication with the option to cancel the download.
the way you save things with the native fs diverge from the way you do it with StreamSaver with native fs you first ask for permission, select a path, name and file format then you are allowed to write to the destination StreamSaver just assumes everything is all fine and dandy and starts writing right away.
I don't know how i should fit native fs into streamsaver anymore. if you have any ideas then i'm all ears and also willing to review some PR.
If i started a new project and I needed to save files then i would not use StreamSaver anymore. my adapter is just as compatible to download stuff without the need of a MITM and dose a better job at it also.
You can test the manual download here: https://jimmywarting.github.io/native-file-system-adapter/example/test.html
Here is ruffly the extracted save method from the test file
// get some dummy gradient image
function img (format) {
var a = document.createElement("canvas"),
b = a.getContext("2d"),
c = b.createLinearGradient(0, 0, 1500, 1500);
a.width = a.height = 3000;
c.addColorStop(0, "red");
c.addColorStop(1, "blue");
b.fillStyle = c;
b.fillRect(0, 0, a.width, a.height);
return new Promise(rs => {
a.toBlob(rs, 'image/' + format, 1)
})
}
download.onclick = async () => {
const opts = {
type: 'save-file',
accepts: [
{ extensions: ['jpg'] },
{ extensions: ['webp'] },
{ mimeTypes: ['image/png'] }
],
excludeAcceptAllOption: true,
_name: 'image.jpg', // fallback if not using native file system
_preferPolyfill: false // default is false
}
// Will either use
// 1. native file system if it is supported
// 2. streamsaver.js method of using a service worker (if a service worker is installed)
// 3. or lastly fallback to a temporary memory blob builder and use `a[download]`
const handle = await chooseFileSystemEntries(opts)
// figure out the format use wants
const format = handle.name.split('.').pop()
// generate a blob image from canvas
const image = await img(format)
const ws = await handle.createWritable()
// write blob
ws.write(image)
ws.close()
}
Saw you lib after i uploaded my adapter to the public yours is more like a shim than a polyfill or ponyfill (but without the sandboxing features)
True, and deliberately so. It adds some convenience features on top, for example, directory browsing.
Do you want to cross references similar projects for publicity? :)
Just did: https://github.com/GoogleChromeLabs/browser-nativefs/blob/master/README.md#alternatives.
I have had plans on adding native fs to streamsaver if only it where possible to include a file name WICG/native-file-system#80
Yeah, hope this is coming soon.
but it isn't so i rather prefer the current method of using content-disposition + service worker solution for a better user experience. It will also allow things such as auto download on user interaction without prompting. and show a native progress indication with the option to cancel the download.
Not sure about your exact use cases, but an interesting alternative might be background fetch.
the way you save things with the native fs diverge from the way you do it with StreamSaver with native fs you first ask for permission, select a path, name and file format then you are allowed to write to the destination StreamSaver just assumes everything is all fine and dandy and starts writing right away.
I see, thanks.
I don't know how i should fit native fs into streamsaver anymore. if you have any ideas then i'm all ears and also willing to review some PR.
If i started a new project and I needed to save files then i would not use StreamSaver anymore. my adapter is just as compatible to download stuff without the need of a MITM and dose a better job at it also.
Agree, there are alternatives now. It was a great solution, though.
You can test the manual download here: https://jimmywarting.github.io/native-file-system-adapter/example/test.html
That's impressive.
Here is ruffly the extracted save method from the test file
// get some dummy gradient image function img (format) { var a = document.createElement("canvas"), b = a.getContext("2d"), c = b.createLinearGradient(0, 0, 1500, 1500); a.width = a.height = 3000; c.addColorStop(0, "red"); c.addColorStop(1, "blue"); b.fillStyle = c; b.fillRect(0, 0, a.width, a.height); return new Promise(rs => { a.toBlob(rs, 'image/' + format, 1) }) } download.onclick = async () => { const opts = { type: 'save-file', accepts: [ { extensions: ['jpg'] }, { extensions: ['webp'] }, { mimeTypes: ['image/png'] } ], excludeAcceptAllOption: true, _name: 'image.jpg', // fallback if not using native file system _preferPolyfill: false // default is false } // Will either use // 1. native file system if it is supported // 2. streamsaver.js method of using a service worker (if a service worker is installed) // 3. or lastly fallback to a temporary memory blob builder and use `a[download]` const handle = await chooseFileSystemEntries(opts) // figure out the format use wants const format = handle.name.split('.').pop() // generate a blob image from canvas const image = await img(format) const ws = await handle.createWritable() // write blob ws.write(image) ws.close() }
This code feels familiar :-)
Just did
Me 2
but an interesting alternative might be background fetch.
Nah, StreamSaver is not about fetching any resource. it's more about having the possibility to write to a writable stream, you can't do that when it's happening in the background.
This could be a useful api in the feature.
https://github.com/WICG/native-filesystem/blob/master/EXPLAINER.md
Then you wouldn't have to use a service worker, which is a huge +