NiceGUI: File upload and download
All notes in this series:
- NiceGUI: Always show main scrollbar
- NiceGUI: Show a confirmation popup
- NiceGUI: File upload and download
- FastAPI: Pretty print JSON
- NiceGUI with Click, Poetry, auto-reload and classes
- NiceGUI: tkinter error when updating pyplot
- NiceGUI: Bind visibility to arbitrary value
- NiceGUI: Change threshold for binding propagation warning
- NiceGUI with async classes
If your NiceGUI application has some sort of state or configuration, it can be useful to provide a way to save and load that state. We can do that through serializing the state into JSON, and providing a way to download and upload that JSON file. Following is a simple example.
Download state §
To start with, let’s just implement download.
State §
In one file, create a class to contain our state, and serialize it as JSON with a to_json
method.
GUI pages §
In another file, create two GUI pages:
- An implicit1
/
index page (the “auto-index page”):- This provides two fields for modifying the state of “Foo” and “Bar”. The
bind_value
means that the globalCONFIG
object is updated when these GUI fields are modified. - It also provides a link to the
config.json
page. Crucially, this uses.props("download=config.json")
so that when the link is clicked the browser downloads the file, rather than opening it in a new tab2.
- This provides two fields for modifying the state of “Foo” and “Bar”. The
- An explicit
/config.json
page which downloads the state as JSON.
When we run python my_gui.py
, NiceGUI will launch the GUI in our browser at <url>
, which defaults to http://127.0.0.1:8080
.
We can then open each page in a new tab:
<url>/
- This displays the “Foo” and “Bar” input fields, which let us alter the state.
<url>/config.json
- This displays a JSON file with the content
{"foo":3.0,"bar":"hello"}
. To pretty print the JSON, see these notes.
If we change the values in the “Foo” and “Bar” fields, then refresh the config.json
page, we see the values update. This works because “[the] auto-index page is created once on startup and shared across all clients that might connect”3. This approach may get a little hairy if you have many clients using the GUI, since they all have read and write access to the same CONFIG
object, but for a small application with one client it is Good Enough™.
For example, if we set “Foo” to 4
in the GUI, then refresh the config.json
page, it will display {"foo":4.0,"bar":"hello"}
.
Upload state §
To support upload, we need a way to populate our MyState
object from JSON.
State §
Let’s add a from_json
method:
GUI pages §
To upload we will use the ui.upload
element4. When the upload completes, it calls the new state_uploaded
function, which updates the config using CONFIG.from_json
:
We set max_files=1
because by default the ui.upload
element accepts multiple files.
Testing §
To test, create a JSON file:
Then run the GUI, click the plus icon to open the file picker, choose the example.json
file, then click the upload icon to perform the upload. Once uploaded (which should be nearly instantaneous for such a small file), the GUI will update with the values from the JSON file, and the notification “Loaded config: example.json” will show at the bottom of the screen.
Alternative approaches §
If you are happy to let the browser manage the application state, and do not need to download it as JSON, then NiceGUI offers some built-in storage methods that use session cookies.
To create an explicit index page, see these notes. ↩︎
I looked at the documentation and source code to see if there is any way to specify the download property inside the
ui.link
arguments, but there is not. Instead you have to chain it with.props("download=<filename>")
, which adds thedownload
property to the HTMLa
element, telling the browser to download the file rather than open it in a new tab. Use<filename>
to specify the name the browser should give to the downloaded file. ↩︎Quote from the NiceGUI documentation on “Auto-index page” found here. ↩︎
For an even simpler upload example, see the official NiceGUI docs. ↩︎
All notes in this series:
- NiceGUI: Always show main scrollbar
- NiceGUI: Show a confirmation popup
- NiceGUI: File upload and download
- FastAPI: Pretty print JSON
- NiceGUI with Click, Poetry, auto-reload and classes
- NiceGUI: tkinter error when updating pyplot
- NiceGUI: Bind visibility to arbitrary value
- NiceGUI: Change threshold for binding propagation warning
- NiceGUI with async classes