I believe that dcc.send_file expects the path to be local, not in http… If you are using this callback with the sole purpose of download the file, you could consider replacing the button by a html.A component with href pointing at the URL in the public bucket. That’s probably the easiest approach to download a file like this.
Thank you. The final use for this component will not have a button - it will automatically download. I just grabbed this script from the Dash site as an example of what I am trying to achieve.
I know I can make this work by reading the URL into a dataframe and then converting this dataframe into a csv as a download, but this requires unnecessary steps that I was hoping could be avoided.
Thank you. The file is already online. My desire is that the output of the callback returns the file that is online to the users local machine via an automatic download. I apologize if I was clear enough earlier.
No worries. As I said on top, you can accomplish that by using a html.A tag, which will just generate a link. If you really want the visual of a button, then you can wrap the a tag in a button and remove the decoration with custom css (like this). No need for a callback.
Thanks. I am not after a button - I am after making it download automatically (the download file that pops up on the bottom of the screen and shows the progress).
from dash_extensions.enrich import DashProxy, dcc, html, Output, Input, Trigger, NoOutputTransform, TriggerTransform
app = DashProxy(transforms=[NoOutputTransform(), TriggerTransform()], prevent_initial_callbacks=True)
app.layout = html.Div([
html.Button("Download", id="btn_download"), dcc.Store(id="url_to_open")
])
@app.callback(Output("url_to_open", "data"), Trigger("btn_download", "n_clicks"))
def func():
return 'https://filesamples.com/samples/document/csv/sample4.csv'
# Js snipper that opens the url (i.e. invokes download) in a new window.
js_download = """
function download(dataurl) {
const link = document.createElement("a");
link.href = dataurl;
link.click();
}
"""
# Bind client side callback with dummy output, as we just need to run the js snippet.
app.clientside_callback(js_download, Input("url_to_open", "data"))
if __name__ == "__main__":
app.run_server(debug=True, port=7777)
where you create a temporary link and click it to start the download automatically. I guess this is actually a pretty common use case, so it might have made sense to include it in the Download component.