fix(pdf): flag scanned PDFs in pdf-to-text and serve text as UTF-8 (#603)

When a PDF has no text layer (scanned or image-only), pdf-to-text now
returns a 422 that points at the OCR tool instead of a silent empty file,
and text downloads carry charset=utf-8 so UTF-8 Arabic renders correctly
when the .txt is viewed inline.

Fixes #589
This commit is contained in:
SnapOtter
2026-07-21 16:26:43 +08:00
committed by GitHub
parent 43334324c4
commit 7d37f6e6f5
8 changed files with 109 additions and 19 deletions
+11 -3
View File
@@ -82,16 +82,24 @@ export async function pdfRedactPy(
}
/** Extract plain text from a PDF (PyMuPDF get_text). */
export async function pdfTextPy(inPath: string, outTxtPath: string): Promise<{ chars: number }> {
export async function pdfTextPy(
inPath: string,
outTxtPath: string,
): Promise<{ chars: number; hasText: boolean }> {
const stdout = await runDocsScript("doc_text", { path: inPath, out: outTxtPath });
const parsed = parseDocsJson<{ chars?: number; error?: string }>("doc_text", stdout);
const parsed = parseDocsJson<{ chars?: number; hasText?: boolean; error?: string }>(
"doc_text",
stdout,
);
if (parsed.error) {
throw new Error(`doc_text failed: ${parsed.error}`);
}
if (typeof parsed.chars !== "number") {
throw new Error(`doc_text failed: ${stdout.slice(0, 200)}`);
}
return { chars: parsed.chars };
// Fall back to a chars>0 heuristic if an older sidecar omits hasText.
const hasText = parsed.hasText ?? parsed.chars > 0;
return { chars: parsed.chars, hasText };
}
/** PDF to DOCX conversion (pdf2docx). Long-running: 5 min timeout. */