Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross-browser workaround that doesn't require an external host #348

Open
DavidBuchanan314 opened this issue Oct 28, 2024 · 0 comments
Open

Comments

@DavidBuchanan314
Copy link

DavidBuchanan314 commented Oct 28, 2024

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

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant