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')
2 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,