107 lines
3.8 KiB
Python
107 lines
3.8 KiB
Python
from fastapi import APIRouter, File, HTTPException, UploadFile, status
|
|
|
|
from app.schemas.document import (
|
|
DocumentInfoResponse,
|
|
PageInfoResponse,
|
|
PermissionsResponse,
|
|
)
|
|
from app.services import engine
|
|
from app.services.store import document_store
|
|
|
|
router = APIRouter(prefix="/documents", tags=["documents"])
|
|
|
|
def make_document_response(d: dict) -> DocumentInfoResponse:
|
|
pages_list = []
|
|
if "doc_instance" in d:
|
|
doc = d["doc_instance"]
|
|
for i in range(doc.page_count):
|
|
try:
|
|
page = doc.get_page(i)
|
|
pages_list.append(PageInfoResponse(index=i, width=page.width, height=page.height))
|
|
except Exception:
|
|
pass
|
|
perms = d.get("permissions")
|
|
return DocumentInfoResponse(
|
|
id=d["id"],
|
|
filename=d["filename"],
|
|
sizeBytes=d["sizeBytes"],
|
|
totalPages=d["totalPages"],
|
|
pageWidth=d.get("pageWidth", 612.0),
|
|
pageHeight=d.get("pageHeight", 792.0),
|
|
uploadedAt=d["uploadedAt"],
|
|
status=d["status"],
|
|
pages=pages_list,
|
|
permissions=PermissionsResponse(**perms) if perms else PermissionsResponse(),
|
|
)
|
|
|
|
|
|
@router.post("", response_model=DocumentInfoResponse, status_code=status.HTTP_201_CREATED)
|
|
async def upload_document(file: UploadFile = File(...), password: str = "") -> DocumentInfoResponse:
|
|
if not engine.is_available():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
|
detail="Engine bridge (bindings/python) not yet available.",
|
|
)
|
|
|
|
bytes_data = await file.read()
|
|
try:
|
|
pdfengine = engine.require()
|
|
doc = pdfengine.PdfDocument.load_from_memory(bytes_data, password)
|
|
info = document_store.add_document(file.filename, bytes_data, doc)
|
|
return make_document_response(info)
|
|
except ValueError as e:
|
|
detail = str(e)
|
|
if "Password required" in detail:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED, detail="Password required"
|
|
)
|
|
elif "Invalid password" in detail:
|
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid password")
|
|
else:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=detail)
|
|
except Exception as e:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST, detail=f"Failed to load PDF: {e!s}"
|
|
)
|
|
|
|
|
|
@router.get("", response_model=list[DocumentInfoResponse])
|
|
def list_documents() -> list[DocumentInfoResponse]:
|
|
if not engine.is_available():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
|
detail="Engine bridge (bindings/python) not yet available.",
|
|
)
|
|
|
|
docs = document_store.list_documents()
|
|
return [make_document_response(d) for d in docs]
|
|
|
|
|
|
@router.get("/{document_id}", response_model=DocumentInfoResponse)
|
|
def get_document(document_id: str) -> DocumentInfoResponse:
|
|
if not engine.is_available():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
|
detail="Engine bridge (bindings/python) not yet available.",
|
|
)
|
|
|
|
d = document_store.get_document(document_id)
|
|
if not d:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document not found")
|
|
|
|
return make_document_response(d)
|
|
|
|
|
|
@router.delete("/{document_id}")
|
|
def delete_document(document_id: str):
|
|
if not engine.is_available():
|
|
raise HTTPException(
|
|
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
|
detail="Engine bridge (bindings/python) not yet available.",
|
|
)
|
|
|
|
deleted = document_store.delete_document(document_id)
|
|
if not deleted:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Document not found")
|
|
|
|
return {"success": True} |