I’m looking for an intermediate example of an app which you can upload a file and download a file.
I’m trying to find something between the docs (which give examples for notebook dev):
https://panel.holoviz.org/reference/widgets/FileInput.html
https://panel.holoviz.org/reference/widgets/FileDownload.html
and more extensive app examples:
https://panel.holoviz.org/gallery/simple/file_download_examples.html
https://panel.holoviz.org/gallery/param/download_upload_csv.html
Ideally I would use something like panel serve app.py --show --autoreload
for the app.
The app would have you upload a csv file and download it again.
You can generate a csv as:
import pandas as pd
pd.DataFrame({"a": [0]}).to_csv("in.csv", index=False)
In my head the app would look something like:
import io
import panel as pn
import pandas as pd
pn.extension()
file_input = pn.widgets.FileInput()
pn.panel(file_input).servable()
if file_input.value is not None:
df = pd.read_csv(io.BytesIO(file_input.value))
file_download = pn.widgets.FileDownload(
io.BytesIO(df.to_csv().encode()), filename="out.csv"
)
pn.panel(file_download).servable()
I’m pretty sure i’m missing some param usage for this or using bind as @hoxbro showed here: Convert CSV into Dataframe using FileInput - #4 by Hoxbro
I have some streamlit code which does what I expect:
import pandas as pd
import streamlit as st
uploaded_file = st.file_uploader(label="Choose a file")
if uploaded_file is not None:
df = pd.read_csv(uploaded_file)
st.download_button(
label="Download data",
data=df.to_csv(index=False),
file_name="out.csv",
)
Hoxbro
July 20, 2022, 6:57am
2
You need to use callback
of the file_download
:
import io
import panel as pn
pn.extension()
def _callback():
if file_input.value is not None:
return io.BytesIO(file_input.value)
else:
return io.BytesIO() # For no file_input
file_input = pn.widgets.FileInput()
file_download = pn.widgets.FileDownload(
filename="out.csv",
callback=_callback,
)
pn.Column(file_input, file_download).servable()
1 Like
Thanks @Hoxbro . Here is the same with a mini pandas ETL. Not sure how to hide/not allow clicking the download button before a file is uploaded.
import io
import pandas as pd
import panel as pn
pn.extension()
def _callback():
if file_input.value is not None:
df = pd.read_csv(io.BytesIO(file_input.value))
return io.BytesIO(df.iloc[0].to_csv(index=False).encode())
else:
return io.BytesIO()
file_input = pn.widgets.FileInput(accept=".csv", mime_type="text/csv")
file_download = pn.widgets.FileDownload(
filename="out.csv",
callback=_callback,
name="Upload csv first then press download button below",
)
pn.Column(file_input, file_download).servable()
Hoxbro
July 20, 2022, 12:22pm
4
Here I would use bind
import io
import panel as pn
pn.extension()
def _callback():
if file_input.value is not None:
return io.BytesIO(file_input.value)
else:
return io.BytesIO() # For no file_input
def _disable_download(event):
if file_input.value is None:
file_download.disabled = True
else:
file_download.disabled = False
file_input = pn.widgets.FileInput()
file_download = pn.widgets.FileDownload(
filename="out.csv", callback=_callback, disabled=True
)
pn.bind(_disable_download, file_input.param.value, watch=True)
pn.Column(file_input, file_download).servable()
1 Like
This is awesome! Thanks @Hoxbro . Thanks for helping extend my app in a way that I can easily understand what’s going on.
Final python code for my mini pandas ETL for completeness:
import io
import pandas as pd
import panel as pn
pn.extension()
def _callback():
if file_input.value is not None:
df = pd.read_csv(io.BytesIO(file_input.value))
return io.BytesIO(df.iloc[0].to_csv(index=False).encode())
else:
return io.BytesIO()
def _disable_download(event):
if file_input.value is None:
file_download.disabled = True
else:
file_download.disabled = False
file_input = pn.widgets.FileInput(accept=".csv", mime_type="text/csv")
file_download = pn.widgets.FileDownload(
filename="out.csv",
callback=_callback,
disabled=True,
)
pn.bind(_disable_download, file_input.param.value, watch=True)
pn.Column(file_input, file_download).servable()
2 Likes
mycarta
December 14, 2022, 4:26pm
6
Are you able to show an example (even as GIF) of your app at work?
1 Like