-
-
Notifications
You must be signed in to change notification settings - Fork 437
Open
Description
The gist of it is, stream the file to disk using OPFS, then finally "download" the file via a blob URI (so that it ends up as a regular user-accessible file in their Downloads folder).
const root = await navigator.storage.getDirectory();
const handle = await root.getFileHandle("file.txt", { create: true });
const writable = await handle.createWritable(); // returns a FileSystemWritableFileStream
await writable.write(new Uint8Array(10));
await writable.write(new Uint8Array(10));
await writable.close();
const file = await handle.getFile(); // nb, this is a "File" object, not a regular blob
const uri = window.URL.createObjectURL(file);
console.log(uri);
// should be able to use browser.downloads.download() from webextension context (untested)
const a = document.createElement("a");
a.style.display = "none";
a.download = "file.txt";
a.href = uri;
document.body.appendChild(a);
a.click();
// can't delete straight away! this is a race condition. not sure the best way to do this...
//await root.removeEntry("file.txt");(This is just a PoC and not a productionized impl)
Pros
- Good cross-browser support: https://caniuse.com/mdn-api_storagemanager_getdirectory
- Does not involve service workers or any external servers.
- Should work fine in the context of a WebExtension (not yet tested!)
- Simple
Cons
- Does not work at all in Firefox private tabs :(
- Only works in "secure" contexts.
- OPFS has file size limits, but in practice these limits are quite generous: https://developer.mozilla.org/en-US/docs/Web/API/Storage_API/Storage_quotas_and_eviction_criteria.
- The total free disk space required is double the actual size of the file, because it must temporarily exist in both OPFS and the user's Downloads folder.
- It's hard to decide when to delete the file from OPFS once you're done with it, because you can't tell when the final download is complete. A fixed delay would probably be Good Enough but it'd still be a race condition.
Unknowns
- I haven't tested in Safari at all
- I haven't yet tested for sure that it can handle larger-than-RAM files, but in principle it should.
Given the significant Firefox-private-tab limitation I'd understand if you have no interest in integrating this (or as part of the ponyfill), but I figured I'd leave it here for anyone else looking for alternative approaches.
Metadata
Metadata
Assignees
Labels
No labels