Spaces:
Sleeping
Sleeping
| """Pull plain text out of uploaded PDF and Word documents.""" | |
| from __future__ import annotations | |
| import io | |
| class ExtractionError(Exception): | |
| """Raised when a document yields no usable text.""" | |
| def extract_text(file_name: str, data: bytes) -> str: | |
| """Return the text of a .pdf, .docx, or .txt file given its raw bytes.""" | |
| name = file_name.lower() | |
| if name.endswith(".pdf"): | |
| return _from_pdf(data) | |
| if name.endswith(".docx"): | |
| return _from_docx(data) | |
| if name.endswith(".txt"): | |
| return data.decode("utf-8", errors="ignore") | |
| raise ExtractionError(f"Unsupported file type: {file_name}") | |
| def _from_pdf(data: bytes) -> str: | |
| from pypdf import PdfReader | |
| reader = PdfReader(io.BytesIO(data)) | |
| if reader.is_encrypted: | |
| try: | |
| reader.decrypt("") | |
| except Exception as exc: # noqa: BLE001 - surfaced to the user | |
| raise ExtractionError("This PDF is encrypted and cannot be read.") from exc | |
| text = "\n".join((page.extract_text() or "") for page in reader.pages) | |
| if not text.strip(): | |
| raise ExtractionError( | |
| "No text found. The PDF is likely scanned (images only); " | |
| "OCR would be needed to read it.") | |
| return text | |
| def _from_docx(data: bytes) -> str: | |
| from docx import Document | |
| document = Document(io.BytesIO(data)) | |
| parts = [p.text for p in document.paragraphs] | |
| for table in document.tables: | |
| for row in table.rows: | |
| parts.extend(cell.text for cell in row.cells) | |
| text = "\n".join(p for p in parts if p) | |
| if not text.strip(): | |
| raise ExtractionError("No text found in the document.") | |
| return text | |