-
fix(processors): surface clean error for corrupted or truncated PDFs (#527)
发布于
2026-05-21 01:32:29 +00:00 Objective: A PDF whose %PDF- header is present but whose body is corrupt or truncated (download interrupted near the end, missing trailing xref) currently surfaces a 17-line veraPDF IOException stack trace on stdout.
The user has no way to tell whether their file is broken or whether opendataloader-pdf is.
Approach: Wrap only the new PDDocument(pdfName) call in DocumentProcessor.preprocessing with a try-catch on IOException and rethrow as InvalidPdfFileException with a distinct message ending in "corrupted or truncated content".
InvalidPasswordException is re-thrown as-is so the existing password-handling branch in CLIMain still wins.
Other failure modes (parseStructureTreeRoot, parseChunks, hybrid path) remain on the existing SEVERE path — only the header-present-body-broken case is reclassified.
Because InvalidPdfFileException is already handled by CLIMain.processFile, no CLI changes are needed: CLI-argument input prints "Error: ..." to stdout and exits 1; a corrupt file inside a directory logs WARNING and continues (preserves batch-folder semantics).
The original veraPDF exception is preserved as getCause() so Java API consumers can still inspect the root cause for diagnostics.
Evidence: mvn -pl opendataloader-pdf-cli -am test runs DocumentProcessorMagicNumberTest at 4/4 pass and CLIMainTest at 23/23 pass.
Manual end-to-end against the built jar:
Scenario Expected Actual Real PDF with last 2000 bytes cut off friendly stdout, exit 1, no stack trace "Error: 'real_truncated.pdf' is not a valid PDF file (corrupted or truncated content)." exit 1 JPEG renamed to .pdf distinct missing-header wording "Error: 'fake.pdf' is not a valid PDF file (missing %PDF- header)." exit 1 Intact PDF exit 0, JSON written exit 0, JSON generated Directory with 1 truncated + 1 intact intact processed, truncated skipped with WARNING, exit 0 WARNING "'truncated.pdf' ... Skipping.", good.json written, exit 0 npm run sync not required — no CLI option definitions changed.
Python/Node wrappers pass Java stdout and exit code through unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
下载附件