Download pdf/png from matplotlib in Streamlit


I have made a app that automate a sheetpile-construction- prosess.

As seen on the image, the app will show calculations from the backend. Theese calculations juses matplotlib.plt fig=plt.plot() etc.
In streamlit i then use st.pyplot( and st.pyplot(fig) to show the figure.

But I like to share this app to the web, and then the app need to be able to download theese figures as shown on demand.

1.This can be done by input a path in streamlit, and then use the plt.savefig(path,name_of_file+".pdf")
This is easly done in “local”-mode, however, when uploading to the web, I have not been able to make inputs to local paths/folder etc in streamlit. Any tips on how this can be done?
2. The second option and possibly the best one, is to be able to directly download the each of the figures as png/pdf or to download them all to one report.

def create_download_link(val, filename):
    b64 = base64.b64encode(val)  # val looks like b'...'
    return f'<a href="data:application/octet-stream;base64,{b64.decode()}" download={filename}.pdf">Download file</a>'

  if export_as_pdf=="Yes":
        pdf = FPDF()
        for fig in figs:
            with NamedTemporaryFile(delete=False, suffix=".png") as tmpfile:
        html = create_download_link(pdf.output(dest="S").encode("latin-1"), "Resultatfil")
        st.markdown(html, unsafe_allow_html=True)

The fig list is appended matplotlib figures:
as shown here: image
The problem is then that the generated PDF is blank.

Anyone that got any tips on this? :smiley:

I see a lot of stackoverflow posts saying you should reverse the order of show and savefig because show supposedly blocks/prevents export, so like this:

plt.savefig()   # <-- save first      # <-- then display
1 Like

Thank you, it works! :smiley:

Other question, do you have any tips on how to connect to a local path/folder from streamlit sharing/ heroku?

save_path=st.sidebar.text_input(“save path location”)
if not len(save_path)==0:
if not os.path.exists(save_path):
st.sidebar.warning(“no path”)

I then want to os.listdir(save_path) and get the files from the path that the user inputs.
This works fine in localhost, but deployed on the web it won’t work.