Setup
I have a primarily offline Electron/web hybrid application that, at some point, requires a "Save As" function that works reliably. In browsers, I implement this function by programmatically triggering a click on an <a>
with HTML5 download attribute:
let anchor = document.createElement("a");
let href = window.URL.createObjectURL(new Blob([fileContents]));
anchor.href = href;
anchor.download = settings.defaultFilename;
anchor.click();
It is then up to the browser and its settings how the "Save As" functionality itself is carried out, some will show the Save As dialog, some will download directly into the user's "downloads" folder without asking.
Of course, I'm running preliminary checks for browsers that clearly don't support the download
attribute, and show a clear warning on app startup, e.g.:
if (typeof anchor.download === "undefined") {
throw new Error("Your browser does not support saving your project.");
}
Problem
Now this download is an important part of my app workflow. It is important for the "download" to succeed after initiated, as otherwise the user may lose a lot of work.
I can "wait" for the download to finish before proceeding and it is absolutely fine if the download fails, as long as the user is notified of the failure.
Is there a way I can ensure the file has finished "downloading" or detect if it "failed"? (besides asking the user to see for himself, which is not an option from the perspective of our workflow)
Why not store the data on a server?
- Because my app should work offline and data might be large (i.e. several GB).
Why not keep the data in e.g. localStorage
and IndexedDB
?
- Storing data in here will accumulate and the browser will be increasingly likely to delete it if the user starts running out of free space. This "Save As" function is actually extracting data from localStorage and IndexedDB for permanent storage on the user's device.
Why not use a solution like Detect when browser receives file download ?
- Because those answers all assume an Online app model with an always available server, while my app needs to work even offline, and also save a file that only exists in the app memory.