Is it possible that use pikepdf to open a uploaded pdf file?

Hi my lovely community,
I have a small local python app and it works well with using pikepdf to remove user password of pdf file. Now I want to move it to web but stucked for several days.
The problem is here:

from pikepdf import Pdf
uploaded_pdf_file=st.file_uploader('Upload Your PDF File',type=['pdf'])
if uploaded_pdf_file is not None:
        pdffile = Pdf.open(uploaded_pdf_file, allow_overwriting_input = True)
        pdf_result=pdffile.save('unlocked.pdf')     

It reports ValueError: “allow_overwriting_input=True” requires “open” first argument to be a file path
Is it possible that use pikepdf to open a uploaded pdf file? How?
I did lots of search. It seems like there were very few articles about streamlit and pikepdf (Maybe as PDF is evil).

Try this here as a starting point:

import streamlit as st
from pikepdf import Pdf

uploaded_pdf_file = st.file_uploader('Upload Your PDF File', type=['pdf'])

if uploaded_pdf_file is not None:
    pdffile = Pdf.open(uploaded_pdf_file)
    # do some processing here with the pdf file
    pdffile.save('unlocked.pdf')

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

st.download_button(label="Download unlocked.pdf",
            data=PDFbyte,
            file_name="unlocked.pdf",
            mime='application/octet-stream')
1 Like

Here an even better quick example without writing temporarily to disk:

import io
import streamlit as st
from pikepdf import Pdf

filestream = io.BytesIO()
uploaded_pdf_file = st.file_uploader('Upload Your PDF File', type=['pdf'])

if uploaded_pdf_file:
    if len(uploaded_pdf_file.getvalue()) > 0:
        st.text(f'uploaded_pdf_file: {len(uploaded_pdf_file.getvalue())} bytes')
        pdffile = Pdf.open(uploaded_pdf_file)
        # do some processing here with the pdf file
        pdffile.save(filestream)

if filestream:
    if len(filestream.getvalue()) > 0:
        st.download_button(label="Download unlocked.pdf",
                data=filestream.getvalue(),
                file_name="unlocked.pdf",
                mime='application/octet-stream')
        st.text(f'filestream: {len(filestream.getvalue())} bytes')
2 Likes

Thank you so much! Your method works! It really saved my days!
A tips for later reader if any:
My streamlit version is 0.80.0. To use st.download_button, you have to upgrade it to 1.7.0.