Reputation: 99
I have an app that produces a zip file that I want to download using dcc.download. I think the zip-creation works fine (I tested it by downloading it directly using "with"). But how its possible to download the stream archive
using dcc.download? How do I have to hand it over the correct way?
My code below:
import io
from os import close
import dash
from dash.dependencies import Output, Input
from dash_extensions.snippets import send_bytes
import dash_html_components as html
import dash_core_components as dcc
import base64
import matplotlib.pyplot as plt
import zipfile
from io import BytesIO
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([html.Button("Download zip", id="btn_txt"),
dcc.Download(id="download-text")]
)
@app.callback(
Output("download-text", "data"),
Input("btn_txt", "n_clicks"),
prevent_initial_call=True,
)
def func(n_clicks):
archive = BytesIO()
with zipfile.ZipFile(archive, mode="w") as zf:
for i in range(3):
plt.plot([i, i])
buf = io.BytesIO()
plt.savefig(buf)
plt.close()
img_name = "fig_{:02d}.png".format(i)
zf.writestr(img_name, buf.getvalue())
return send_bytes(archive.read(), "some_name.zip")
if __name__ == "__main__":
app.run_server(debug=False)
Upvotes: 2
Views: 3785
Reputation: 6024
The first argument of send_bytes
should be a function handle that writes content to BytesIO
. Adopting your example, the code would be
import io
import dash
import dash_html_components as html
import dash_core_components as dcc
import matplotlib.pyplot as plt
import zipfile
from dash.dependencies import Output, Input
app = dash.Dash(prevent_initial_callbacks=True)
app.layout = html.Div([html.Button("Download zip", id="btn_txt"), dcc.Download(id="download-text")])
@app.callback(Output("download-text", "data"), Input("btn_txt", "n_clicks"))
def func(n_clicks):
def write_archive(bytes_io):
with zipfile.ZipFile(bytes_io, mode="w") as zf:
for i in range(3):
plt.plot([i, i])
buf = io.BytesIO()
plt.savefig(buf)
plt.close()
img_name = "fig_{:02d}.png".format(i)
zf.writestr(img_name, buf.getvalue())
return dcc.send_bytes(write_archive, "some_name.zip")
if __name__ == "__main__":
app.run_server()
Upvotes: 4