FileKit icon indicating copy to clipboard operation
FileKit copied to clipboard

Support file saver dialog for JS and WASM targets too

Open mipastgt opened this issue 5 months ago • 12 comments

Hi, it would be nice if the file saver dialog would be available for the web platforms too. An implementation could be based on the very popular FileSaver library.

mipastgt avatar Aug 01 '25 09:08 mipastgt

Hi @mipastgt! Thanks for creating this issue! I'll check it out.

vinceglb avatar Aug 03 '25 10:08 vinceglb

It could be as simple as that:

In build.gradle.kts in wasmJsMain.dependencies

implementation(npm("file-saver", "2.0.5"))

In your code:

@ExperimentalWebApi
@JsModule("file-saver")
external class FileSaverJs {
    companion object {
        fun saveAs(blob: Blob, fileName: String)
    }
}

mipastgt avatar Aug 03 '25 11:08 mipastgt

It doesn't look like file-saver is highly required in current case. Repo looks like unsupported :(

Following snippet can be used instead.

turansky avatar Aug 03 '25 19:08 turansky

Yes, but note the comment in this more recent version of the snippet.

mipastgt avatar Aug 03 '25 21:08 mipastgt

@mipastgt file-saver provides other behaviour?

turansky avatar Aug 03 '25 23:08 turansky

Yes, as far as I can tell (I tried it on my mac) it always shows the dialog in the same way as you would expect it from a desktop application.

mipastgt avatar Aug 04 '25 07:08 mipastgt

I'm testing file-saver library on mac with chrome but when I call saveAs(:blob, :fileName), it doesn't open the file saver dialog. However, the file is properly downloaded in the download folder.

It behaves the same way as FileKit.download() (https://filekit.mintlify.app/dialogs/file-saver#download-file-on-the-web)

I think @mipastgt that in your browser settings, you have the option "Ask where to save each file before downloading" enabled as suggested in this issue: https://github.com/eligrey/FileSaver.js/issues/630

Finally, I'm not sure if forcing the browser to open to file saver dialog is possible. Did I miss something?

vinceglb avatar Aug 20 '25 10:08 vinceglb

Yes, you are right. I just re-checked that and when I disable the "asking" in Chrome, then FileSaver also just saves the file in the default location.

mipastgt avatar Aug 20 '25 11:08 mipastgt

I don't think it is possible to support file saver dialogs for web targets right now. I'm closing this issue, but we can reopen if we found a way to support that in the future.

vinceglb avatar Sep 06 '25 21:09 vinceglb

Works in Chrome - https://developer.mozilla.org/en-US/docs/Web/API/Window/showSaveFilePicker

turansky avatar Sep 06 '25 21:09 turansky

Thanks, I wasn't aware this API existed!

Yesterday I was able to make it work in js and wasm targets on chromium based browsers. Also, I was able to create a PlatformFile from the return of showSaveFilePicker().

But I encountered a problem when I tried to use this API on an unsupported browser like Safari: after calling showSaveFilePicker(), the Compose app crashes and didn't respond at all and log this exception in the console:

JsException: Can't find variable: showSaveFilePicker

The main problem here is that I can't catch the exception with the classic try / catch. The exception is thrown somewhere else in the internals of KMP.

I'm not sure how to handle unsupported web APIs. Is it the responsibility of the developer to check if he can call certain web API or if it is to the library to check (and simplify the developer experience)?

vinceglb avatar Sep 08 '25 11:09 vinceglb

Have you tried following this recommendation? https://developer.chrome.com/docs/capabilities/web-apis/file-system-access#feature_detection

mipastgt avatar Sep 08 '25 11:09 mipastgt