Preview PDF files using browser-native components in streamlit.
No third-party libraries required other than
streamlititself.
streamlit run streamlit_pdf.pyCopy the following code into your
streamlitapplication and invoke thest_show_pdffunction.
import base64
import urllib.request
import streamlit as st
from streamlit.components.v1 import html
def st_show_pdf(
input: str | bytes,
width: str = "100%",
height: str = "100%",
id: str = "",
view: str = "FitH",
timeout: int = 10,
) -> bool:
"""
Display a PDF file in Streamlit
:param input: PDF file path or content
:param width: Display width
:param height: Display height
:param id: Element ID, must be unique
:param view: Display mode `FitH`, `FitV`, `FitB`, `FitBH`, `FitBV`
:param timeout: Request timeout
:return: Whether display succeeded
"""
def content_to_base64(address: str, timeout: int):
try:
if address.startswith(("http://", "https://")):
req = urllib.request.Request(address)
with urllib.request.urlopen(req, timeout=timeout) as response:
if response.status != 200:
raise ValueError(
f"HTTP error: {response.status} {response.reason}"
)
header = response.read(5)
if header != b"%PDF-":
raise ValueError("Not a valid PDF file")
content = header + response.read()
else:
with open(address, "rb") as f:
header = f.read(5)
if header != b"%PDF-":
raise ValueError("Not a valid PDF file")
content = header + f.read()
return base64.b64encode(content).decode("utf-8")
except Exception:
raise ValueError("Failed to read content")
try:
if isinstance(input, str):
base64_pdf = content_to_base64(input, timeout)
elif isinstance(input, bytes):
if input.startswith(b"%PDF-"):
base64_pdf = base64.b64encode(input).decode("utf-8")
else:
raise ValueError("Invalid PDF format")
else:
raise ValueError("Invalid input type")
if id == "":
id = "stPDF_" + str(hash(input))
st.markdown(
f'<embed id="{id}" width="0" height="0" type="application/pdf">',
unsafe_allow_html=True,
)
html(
f"""
<script>
let raw = atob("{base64_pdf}");
let rawLength = raw.length;
let uint8Array = new Uint8Array(rawLength);
while (rawLength--){{
uint8Array[rawLength] = raw.charCodeAt(rawLength);
}}
let fileBlob = new Blob([uint8Array],{{type: "application/pdf"}});
let href = URL.createObjectURL(fileBlob);
let pdf = window.parent.document.getElementById("{id}");
if (pdf) {{
pdf.src = href + "#view={view}";
pdf.width = "{width}";
pdf.height = "{height}";
}}
</script>
""",
height=0,
)
return True
except Exception:
return False