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

Any means to download the file? #38

Closed
me21 opened this issue Jun 7, 2022 · 5 comments
Closed

Any means to download the file? #38

me21 opened this issue Jun 7, 2022 · 5 comments

Comments

@me21
Copy link
Contributor

me21 commented Jun 7, 2022

I'd like to create a button which, when clicked, causes a file to be downloaded in the browser. To my understanding, in regular HTML this is handled by href attribute.

I tried: ui.button('Download configuration file').classes('my-2 mx-4').props('href=https://quasar.dev') which, according to https://quasar.dev/vue-components/button#example--links, I thought, should cause the browser to issue GET request to go to quasar.dev website. But there's no reaction after click.

Or should it be handled with ui.add_route for serving the file and on_click=lambda: ui.open(route_url) button argument?

@me21
Copy link
Contributor Author

me21 commented Jun 7, 2022

Solved it as:

@ui.get('/config.json')
def config_json_response(request: requests.Request):
    return responses.FileResponse(pathlib.Path.home().joinpath(DATA_MANAGER_DIRECTORY, CONFIG_FILENAME))

# somewhere later...

with ui.link(target='/config.json').classes(remove='underline').props('download=config.json'):
    ui.button('Download configuration file').classes('my-2 mx-4')

Is there any better way?

@falkoschindler
Copy link
Contributor

To my understanding, in regular HTML this is handled by href attribute.

Yes, the href attribute points to the location where the resource can be accessed. The server, however, needs to provide the file at this location. Since NiceGUI implements frontend and backend, you need to take care of both.

Using ui.get is totally fine. You could even leave out the request argument. Since version 0.7.28 you can also use ui.add_static_files('/some/route', 'path/to/some/folder'). Then you can access every file in this folder via e.g. `/some/route/file.json'.

Wrapping a button inside a link seems a little weird. Combining a button with ui.open should work:

ui.button('Download', on_click=lambda e: ui.open('/some/route/file.json', e.socket))

Note that without providing the socket, every browser connected to the app would open the file, not only the one that triggered the click event.

@me21
Copy link
Contributor Author

me21 commented Jun 8, 2022

Thanks! I'll update and try that. The line about socket should be probably added to the documentation. It was unclear to me what that argument is for.

UPD: your code opens the file contents in the browser instead of downloading it.

UPD: my bad, had to add non-empty filename argument to FileResponse.

PS: That's funny, Firefox just reloads the page when I click the button. What's more weird, even if I type another URL in the address field, it just reloads the page and doesn't go away from 192.168.7.2:8080. Probably a bug in Firefox 101. In Edge browser, it works as intended.

@falkoschindler
Copy link
Contributor

falkoschindler commented Jun 9, 2022

Yeah, the documentation says "param socket: optional WebSocket defining the target client". That's maybe a little short. I'll add some clarification.

I think whether the file is displayed or downloaded depends on the browser and/or file extension. Good to hear that you found a way to enforce the download.

The Firefox behavior is weird. ui.open doesn't seem to be working at all. Nevertheless, I'll close this card and open a new issue: #42

@me21
Copy link
Contributor Author

me21 commented Jun 9, 2022

So it's not only me? I thought my Firefox extensions could play tricks on me. Oh well.

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

2 participants