file_download
Allows downloading of a file content.
The content to be sent to the user's browser can be a file, a URL, or any data stored as
a buffer of bytes.
The content can be dynamically generated when the user requests it.
Image format
Note that if the content is provided as a buffer of bytes, it can be converted
to image content if and only if you have installed the
python-magic
Python package (as well
as python-magic-bin
if your
platform is Windows).
The download can be triggered when clicking on a button or can be performed automatically (see the auto property).
Properties¶
Name | Type | Default | Description |
---|---|---|---|
(★) |
path|file|URL|ReadableBuffer|None dynamic |
The content to transfer.
|
|
label |
str dynamic |
The label of the button. |
|
on_action |
Callback |
The name of a function that is triggered when the download is terminated (or on user action if content is None).
|
|
auto |
bool |
False | If True, the download starts as soon as the page is loaded. |
render |
bool dynamic |
True | If True, the control is displayed. |
bypass_preview |
bool |
True | If False, allows the browser to try to show the content in a different tab. |
name |
str |
A name proposition for the file to save, that the user can change. |
|
active |
bool dynamic |
True | Indicates if this component is active. |
id |
str |
The identifier that will be assigned to the rendered HTML component. |
|
properties |
dict[str, any] |
Bound to a dictionary that contains additional properties for this element. |
|
class_name |
str dynamic |
The list of CSS class names that will be associated with the generated HTML Element. |
|
hover_text |
str dynamic |
The information that is displayed when the user hovers over this element. |
(★)content
is the default property for this visual element.
Styling¶
All the file download controls are generated with the "taipy-file_download" CSS class. You can use this class name to select the file download controls on your page and apply style.
Usage¶
Default behavior¶
Allows downloading content when content is a file path or some content.
Definition
<|{content}|file_download|>
<taipy:file_download>{content}</taipy:file_download>
import taipy.gui.builder as tgb
...
tgb.file_download("{content}")
Standard configuration¶
The label property can be set to specify the label used as the button text next to the download icon.
The function name provided as on_action is called when the download is done (except if content was set to None, as show in the dynamic content examples below).
The name property is used as the default file name proposed to the user when saving the downloaded file (depending on the browser validation rules).
Definition
<|{content}|file_download|label=Download File|on_action=function_name|name=filename|>
<taipy:file_download label="Download File" on_action="function_name" name="filename">{content}</taipy:file_download>
import taipy.gui.builder as tgb
...
tgb.file_download("{content}", label="Download File", on_action=function_name, name="filename")
Preview file in the browser¶
The file content can be visualized in the browser (if supported and in another tab) by setting bypass_preview to False.
Definition
<|{content}|file_download|don't bypass_preview|>
<taipy:file_download bypass_preview="false">{content}</taipy:file_download>
import taipy.gui.builder as tgb
...
tgb.file_download("{content}", bypass_preview=False)
Automatic download¶
The file content can be downloaded automatically (when the page shows and when the content is set) when auto is set to True.
Definition
<|{content}|file_download|auto|>
<taipy:file_download auto>{content}</taipy:file_download>
import taipy.gui.builder as tgb
...
tgb.file_download("{content}", auto=True)
Dynamic content¶
You can download the entire source code used in this section from the GitHub repository.There are situations when the content to be downloaded cannot or should not be ready before the
user presses the download button.
This happens, for example, if some data generation process needs to query live data or if this
process takes a lot of time and depends on user-defined parameters. In this situation, you may not
want to spend time and resources generating data that may not be used after all.
The property content of the file_download
control can be set to None to handle
these circumstances. In this case, the on_action callback is invoked immediately
after the user has pressed the download button and is in charge of generating the data then
triggering the download operation.
Here is an example of such a situation: an algorithm can generate the digits of the number Pi with
a requested number of digits.
A slider
control lets the user interactively pick the desired precision and a
file_download
control allows to download a CSV file that contains all the generated digits.
Generating all those digits every time the user moves the slider knob would waste CPU time.
We really want to generate the data only when the user presses the download button.
Here is some code that achieves that:
# Initial precision
precision = 10
def pi(precision: int) -> list[int]:
"""Compute Pi to the required precision.
Adapted from https://docs.python.org/3/library/decimal.html
"""
saved_precision = getcontext().prec # Save precision
getcontext().prec = precision
three = Decimal(3) # substitute "three=3.0" for regular floats
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n+na, na+8
d, da = d+da, da+32
t = (t * n) / d
s += t
digits = []
while s != 0:
integral = int(s)
digits.append(integral)
s = (s - integral) * 10
getcontext().prec = saved_precision
return digits
# Generate the digits, save them in a CSV file content, and trigger a download action
# so the user can retrieve them
def download_pi(state):
digits = pi(state.precision)
buffer = io.StringIO()
buffer.write("index,digit\n")
for i, d in enumerate(digits):
buffer.write(f"{i},{d}\n")
download(state, content=bytes(buffer.getvalue(), "UTF-8"), name="pi.csv")
The variable precision is bound to a slider on the page: its value is updated (in the
user's State
), and there is no callback triggered when the slider knob moves. Only the
state variable is updated for later use.
The function download_pi() is invoked as the on_action callback for the
file_download
control, that has its content property set to None. As a result,
when the user presses the download button, download_pi() gets immediately invoked so the data
can be generated. The data can be downloaded to the user's browser using an explicit call to the
function download()
, where we convert the string content to a byte buffer using the bytes()
function.
The control definition looks like this:
Definition
<|{None}|file_download|on_action=download_pi|>
<taipy:file_download on_action="download_pi">{None}</taipy:file_download>
import taipy.gui.builder as tgb
...
tgb.file_download("{None}", on_action=download_pi)
Content in a temporary file¶
You can download the entire source code used in this section from the GitHub repository.In the previous example, we could generate and store all our data in a buffer and then send it so
Taipy would create a data URL to handle the transfer.
There are situations where this is not possible or inefficient. Then, a temporary file must be
created.
But then, after the transfer is performed, we want to remove that file from the server filesystem
since it is no longer needed.
To achieve that, we can use the on_action parameter of the function download()
: it gets
invoked when the transfer is done, so you can perform any task that should be executed after the
file transfer.
Here is some code that demonstrates this. It is a slightly modified version of the example
above, where instead of creating a io.StringIO
buffer to hold the data, we create a
temporary file where we write everything.
The data generation function (pi()) and the control definition remain the same.
Here are the changes to the code compared to the example above:
# Stores the path to the temporary file
temp_path = None
# Remove the temporary file
def clean_up(state):
os.remove(state.temp_path)
# Generate the digits, save them in a CSV temporary file, then trigger a download action
# for that file.
def download_pi(state):
digits = pi(state.precision)
with NamedTemporaryFile("r+t", suffix=".csv", delete=False) as temp_file:
state.temp_path = temp_file.name
temp_file.write("index,digit\n")
for i, d in enumerate(digits):
temp_file.write(f"{i},{d}\n")
download(state, content=temp_file.name, name="pi.csv", on_action=clean_up)
In the new implementation of download_pi(), we create a temporary file to write the data we
want to send.
The path to this file is saved in the state object. This is made possible because the variable
temp_path was declared so that state knows about it.
The call to download()
now sets the content to be transferred to the temporary file path and
sets the on_action parameter that indicates that, when the file transfer is performed, the
function clean_up() should be called.
In clean_up(), we simply delete the temporary file, retrieving its path name from the provided
state.