Download PDF option

Hi Community,

I am trying to create a download option for a pdf file for the end-user. The goal is to enable the user to download the PDF file that is located in the same server where the app is hosted.

I am able to download the file, but the file is not opening after download. The PDFs size varies between 6-12 pages here.

I have tweaked the code a bit from this post. Please help.

import streamlit as st

from fpdf import FPDF

import base64

def create_download_link(val, filename):

    b64 = base64.b64encode(val)

    hreflink = f'<a href="data:application/octet-stream;base64,{b64.decode()}" download="{filename}.pdf">Download file</a>'

    return hreflink

def main():

    menu = ["Home", "PDF", "About"]

    choice = st.sidebar.selectbox("Menu", menu)

   

    if choice == "Home":

        pass

    if choice == "PDF":

        with open("dummy2.pdf", "rb") as pdf_file:

            PDFbyteText = base64.b64encode(pdf_file.read())

        export_as_pdf = st.button("Export Report")

        st.text(type(PDFbyteText))

        if export_as_pdf:

            html = create_download_link(PDFbyteText, "test")

            st.markdown(html, unsafe_allow_html=True)

   

    if choice == "About":

        pass

if __name__ == '__main__':

    main()

Upon opening the downloaded PDF, it throws the below error:

Hello @cs.sabya

There is an official Download Button, did you try to use it with the pdf_file variable?

Have a nice day,
Fanilo

Thank you @andfanilo. This is working for me.

import streamlit as st

with open("dummy.pdf", "rb") as pdf_file:
    PDFbyte = pdf_file.read()

st.download_button(label="Export_Report",
                    data=PDFbyte,
                    file_name="test.pdf",
                    mime='application/octet-stream')
3 Likes

Thanks for sharing back the answer :slight_smile: will definitely help others!

Fanilo

This is by far the best solution to downloading a pdf from Streamlit! :raised_hands::raised_hands::raised_hands:
Solutions within this discussion are also great but Iโ€™ve found the above to be most reliable, straightforward and โ€œstreamlit nativeโ€. I was able to use this hosted on Heroku to download pdfs to the client.
Thank you @cs.sabya!

1 Like

Thank you @Tobias-Fechner. Glad that it was helpful for you.

Hi,
I am trying to create a PDF template that will include a name given by the user. I want to download the PDF. However, I am finding some problems. This error is displayed when I try to run the app: RuntimeError: Invalid binary data format: <class 'fpdf.fpdf.FPDF'>
This is my code:

import streamlit as st
from fpdf import FPDF

st.header('PDF generator - test')
button1 = st.button('PDF')

if button1:
    name = st.text_input('Name', value='')
    pdf = FPDF('P', 'mm', 'A4')
    pdf.add_page()
    pdf.set_font(family='Times', size=16)
    pdf.cell(40, 50, txt=name)

    st.download_button('Download PDF',
                       data=pdf,
                       file_name='pdf_test.pdf'
                       )

Any suggestion to solve this problem?
Thanks in advance,

@Tiago_Coutinho, did you find an answer?

The documentation page for download_button says that the data argument must be str or bytes or file.

The FPDF object is neither of those. You can use the output method to get bytes from the FPDF object.

5 posts were split to a new topic: Using PyLaTeX with Streamlit

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.