Merge branch 'dev' of https://gitea.maskantech.in/gitea_admin/pdf into furqan
This commit is contained in:
@@ -737,3 +737,104 @@ def export_document(document_id: str):
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
|
||||
|
||||
class TextObjectResponse(BaseModel):
|
||||
text: str
|
||||
fontName: str
|
||||
fontSize: float
|
||||
tm: list[float]
|
||||
|
||||
@router.get("/{document_id}/pages/{page_index}/text_objects", response_model=list[TextObjectResponse])
|
||||
def get_text_objects(document_id: str, page_index: int) -> list[TextObjectResponse]:
|
||||
if not engine.is_available():
|
||||
raise HTTPException(status_code=501, detail="Engine not available")
|
||||
|
||||
doc_info = document_store.get_document(document_id)
|
||||
if not doc_info:
|
||||
raise HTTPException(status_code=404, detail="Document not found")
|
||||
|
||||
pdfengine = engine.require()
|
||||
|
||||
import os
|
||||
# For StreamEditor we need a real file path. If it's loaded from memory, we need to save it to a temp file.
|
||||
# In this MVP, we assume the file was saved somewhere, but actually document_store keeps it in memory.
|
||||
# Wait, doc_store has doc_info["filename"] and bytes_data. Let's write bytes to a temp file.
|
||||
import tempfile
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
|
||||
tmp.write(doc_info["bytes_data"])
|
||||
tmp_path = tmp.name
|
||||
|
||||
try:
|
||||
editor = pdfengine.StreamEditor(tmp_path)
|
||||
objects = editor.extract_text_objects(page_index)
|
||||
|
||||
result = []
|
||||
for obj in objects:
|
||||
# obj["text"] is now returned as bytes from C++
|
||||
text_str = obj["text"].decode("latin-1") if isinstance(obj["text"], bytes) else obj["text"]
|
||||
result.append(TextObjectResponse(
|
||||
text=text_str,
|
||||
fontName=obj["fontName"],
|
||||
fontSize=obj["fontSize"],
|
||||
tm=obj["tm"]
|
||||
))
|
||||
return result
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
finally:
|
||||
if os.path.exists(tmp_path):
|
||||
os.remove(tmp_path)
|
||||
|
||||
|
||||
class UpdateTextObjectRequest(BaseModel):
|
||||
new_text: str
|
||||
|
||||
|
||||
@router.put("/{document_id}/pages/{page_index}/text_objects/{object_index}")
|
||||
def replace_text_object(document_id: str, page_index: int, object_index: int, req: UpdateTextObjectRequest) -> dict:
|
||||
if not engine.is_available():
|
||||
raise HTTPException(status_code=501, detail="Engine not available")
|
||||
|
||||
doc_info = document_store.get_document(document_id)
|
||||
if not doc_info:
|
||||
raise HTTPException(status_code=404, detail="Document not found")
|
||||
|
||||
pdfengine = engine.require()
|
||||
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
|
||||
tmp.write(doc_info["bytes_data"])
|
||||
tmp_path = tmp.name
|
||||
|
||||
out_path = tmp_path + ".out.pdf"
|
||||
|
||||
try:
|
||||
editor = pdfengine.StreamEditor(tmp_path)
|
||||
# Convert frontend string back to exact bytes using latin-1
|
||||
new_text_bytes = req.new_text.encode("latin-1")
|
||||
success = editor.replace_text_object(page_index, object_index, new_text_bytes, out_path)
|
||||
if not success:
|
||||
raise HTTPException(status_code=400, detail="Failed to replace text object (not found or identical)")
|
||||
|
||||
# Update the document store with the new bytes
|
||||
with open(out_path, "rb") as f:
|
||||
new_bytes = f.read()
|
||||
|
||||
# Reload doc instance
|
||||
doc_instance = pdfengine.PdfDocument.load_from_memory(new_bytes, "")
|
||||
|
||||
# Update the store
|
||||
doc_info["bytes_data"] = new_bytes
|
||||
doc_info["doc_instance"] = doc_instance
|
||||
|
||||
return {"success": True}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
finally:
|
||||
if os.path.exists(tmp_path):
|
||||
os.remove(tmp_path)
|
||||
if os.path.exists(out_path):
|
||||
os.remove(out_path)
|
||||
|
||||
Reference in New Issue
Block a user