PdfReader / app.py
Corran's picture
Update app.py
b9a7172 verified
import solara, ipyreact
from pathlib import Path
import base64
import requests
def pdf_url_to_base64(url):
response = requests.get(url)
if response.status_code == 200:
pdf_bytes = response.content
base64_encoded = base64.b64encode(pdf_bytes).decode("utf-8")
return base64_encoded
else:
print("Failed to fetch PDF from URL:", url)
return None
ipyreact.define_module("ts-pdf", "./tp.mjs")
ipyreact.define_import_map({
"pdfjs-dist": "https://esm.sh/pdfjs-dist@2.16.105/build/pdf.worker.js",
})
@solara.component
def PDFViewer(type,pdf):
if type=="bytes":
pdf_bytes=pdf
else:
pdf_bytes=pdf_url_to_base64(pdf)
app = ipyreact.ValueWidget(_esm=
"""
import React, { useEffect } from 'react';
import { AnnotEventDetail, CustomStampEventDetail, TsPdfViewer, TsPdfViewerOptions } from 'ts-pdf';
const PdfViewerComponent = () => {
useEffect(() => {
const mobileVhHack = () => {
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
};
mobileVhHack();
window.addEventListener("resize", mobileVhHack);
return () => {
window.removeEventListener("resize", mobileVhHack);
};
}, []);
var arrayBuffer = base64ToArrayBuffer('"""+pdf_bytes+"""');
function base64ToArrayBuffer(base64) {
var binaryString = window.atob(base64);
var binaryLen = binaryString.length;
var bytes = new Uint8Array(binaryLen);
for (var i = 0; i < binaryLen; i++) {
var ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
var blob = new Blob([arrayBuffer], {type: "application/pdf"});
var link = window.URL.createObjectURL(blob);
useEffect(() => {
const run = async () => {
const options: TsPdfViewerOptions = {
containerSelector: "#pdf-main-container",
workerSource: "https://cdn.jsdelivr.net/npm/pdfjs-dist@2.16.105/build/pdf.worker.js",
userName: "corran",
fileButtons: ["close", "save"],
comparableFileButtons: ["open", "close"],
annotChangeCallback: (detail: AnnotEventDetail) => {
if (detail.type === "focus" || detail.type === "select" || detail.type === "render") {
return;
}
console.log(detail);
},
customStampChangeCallback: (detail: CustomStampEventDetail) => {
// console.log(JSON.stringify(detail.stamp));
},
};
const viewer = new TsPdfViewer(options);
// viewer.importAnnotationsFromJson(dtos);
// }, 5000);
// for debug
window["pdfViewer"] = viewer;
await viewer.openPdfAsync(link);
};
run();
// Clean up function
return () => {
// Perform any cleanup of the effect here
};
}, []);
return (
<div style={{
position: "relative",
minWidth: "320px",
width: "100vw",
height: "calc(var(--vh, 1vh) * 100)",
margin: "0",
backgroundColor: "var(--tspdf-color-bg)",
transition: "height .25s ease"
}}>
<style>
{`
.abs-stretch {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
`}
</style>
<div className="test-container abs-stretch">
<div id="pdf-main-container" className="abs-stretch">
{/* Your PDF content will be rendered here */}
</div>
</div>
</div>
);
};
export default PdfViewerComponent;
""")
solara.display(app)
@solara.component
def Reader():
solara.Style("""
#app > div > div:nth-child(2) >
div:nth-child(2){
display: none;
}
""")
router = solara.use_router()
path = router.path
if "bytes=" in path:
data=path.split("bytes=")[-1]
PDFViewer("bytes",data)
elif "url=" in path:
data=path.split("url=")[-1]
PDFViewer("url",data)
else:
solara.Markdown("Invalid PDF")
solara.Markdown(path)
routes = [
solara.Route(
"reader",
component=Reader,
),
]
Reader()