TIKA-4856: /unpack/thumbnail returns the document thumbnail with its metadata - #3096
TIKA-4856: /unpack/thumbnail returns the document thumbnail with its metadata#3096dschmidt wants to merge 14 commits into
Conversation
… metadata Parses in unpack mode with a fixed configuration (the first PDF page and EMF/WMF images rendered, THUMBNAIL and RENDERING embedded documents extracted with their metadata), then picks the raster THUMBNAIL directly below the document, the rendering of a vector THUMBNAIL, or the RENDERING of the first page, and answers with JSON: the embedded document's metadata and the image as base64. 204 when the document has no thumbnail.
|
Remarked it as draft as I'm wondering if we need a better concept |
…unpack, thumbnail-defaults in the server config, PDF maxRenderedPages
# Conflicts: # CHANGES.txt
There was a problem hiding this comment.
Pull request overview
Adds first-class thumbnail support to Tika Server by centralizing “thumbnail defaults” (PDF first-page rendering + EMF/WMF thumbnail rendering) and exposing them via query flags and a new convenience endpoint, while also introducing a PDF parser limit to bound rendering without limiting text extraction.
Changes:
- Introduces
ThumbnailDefaultsandThumbnailSelector, enabling consistent server-side thumbnail rendering/selection behavior. - Adds
?renderThumbnails=trueto/rmeta,/unpack, and/unpack/all, plus a new/unpack/thumbnailendpoint returning{metadata, image(base64)}. - Adds
PDFParserConfig.maxRenderedPagesand enforces it in both PDF rendering paths, with new tests.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/UnpackerThumbnailTest.java | End-to-end tests for /unpack/thumbnail and /rmeta?renderThumbnails=true. |
| tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/resource/ThumbnailSelectorTest.java | Unit tests for thumbnail selection precedence rules. |
| tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/resource/ThumbnailDefaultsTest.java | Unit tests for built-in defaults, config overrides, and merge behavior. |
| tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java | Adds /unpack/thumbnail and renderThumbnails query param support for unpack endpoints. |
| tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java | Wires ThumbnailDefaults from server config and exposes them to resources. |
| tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/ThumbnailSelector.java | Implements thumbnail selection logic among embedded docs (thumbnail vs rendering fallback). |
| tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/ThumbnailDefaults.java | Defines built-in thumbnail parser JSON defaults + config override/merge/application logic. |
| tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java | Adds renderThumbnails query param to /rmeta endpoints and applies defaults. |
| tika-serialization/src/main/java/org/apache/tika/config/loader/TikaJsonConfig.java | Adds thumbnail-defaults as a known top-level JSON config key. |
| tika-parsers/.../src/test/java/org/apache/tika/parser/pdf/PDFMaxRenderedPagesTest.java | Tests for maxRenderedPages behavior and JSON config support. |
| tika-parsers/.../src/main/java/org/apache/tika/parser/pdf/PDFParserConfig.java | Adds maxRenderedPages with validation and accessor methods. |
| tika-parsers/.../src/main/java/org/apache/tika/parser/pdf/PDFParser.java | Uses maxRenderedPages to bound rendered page range for PDF rendering. |
| tika-parsers/.../src/main/java/org/apache/tika/parser/pdf/PDF2XHTML.java | Skips per-page rendering after maxRenderedPages for page-end rendering strategy. |
| docs/modules/ROOT/pages/using-tika/server/index.adoc | Documents thumbnail behavior, query flag, endpoint, and config override block. |
| CHANGES.txt | Adds release notes for the new thumbnail capabilities and maxRenderedPages. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| byte[] image; | ||
| try (InputStream is = zip.getInputStream(imageEntry)) { | ||
| image = is.readAllBytes(); | ||
| } |
There was a problem hiding this comment.
Bounded now: the image is capped at 32 MiB (entry size checked, then read one byte past the limit so a wrong size claim cannot slip through), 413 beyond that. Camera previews and page renderings are a few MB at most, so the constant is generous.
|
Mh, maybe the /thumbnail endpoint should have the renderThumbnails param as well. So we can still opt in to rendering while using the selection logic anyhow. So it's a simple consistent switch for pure extraction or more expensive rendering |
…s opt-in everywhere
|
Done: /unpack/thumbnail takes renderThumbnails as well. Without it a request is the cheap extraction of stored thumbnails, rendering is opt-in with the same switch everywhere. |
# Conflicts: # CHANGES.txt
| /** | ||
| * Sends the file name along, as a client would: raw camera formats are | ||
| * detected by their extension. | ||
| */ |
There was a problem hiding this comment.
Updated, the comment predates TIKA-4861.
|
|
||
| /** | ||
| * What only makes sense when the thumbnail is all the caller wants: no | ||
| * text, no OCR, only THUMBNAIL and RENDERING embedded documents extracted, | ||
| * together with their metadata, down to the rendering of a thumbnail | ||
| * (depth 2). With {@code renderThumbnails} the {@link ThumbnailDefaults} | ||
| * are laid under that, the same switch as on the other endpoints; without | ||
| * it only stored thumbnails are found. The request's own parser | ||
| * configuration wins where present. | ||
| */ | ||
| private void configureThumbnailParse(ParseContext pc, boolean renderThumbnails) { | ||
| //the text is not part of the answer: do not extract it | ||
| tikaResource.setupContentHandlerFactory(pc, "ignore"); | ||
| ThumbnailDefaults noOcr = ThumbnailDefaults.none() | ||
| .with("{\"pdf-parser\": {\"ocr\": {\"strategy\": \"NO_OCR\"}}, " | ||
| + "\"tesseract-ocr-parser\": {\"skipOcr\": true}}"); | ||
| (renderThumbnails ? tikaResource.getThumbnailDefaults().with(noOcr) : noOcr).applyTo(pc); |
There was a problem hiding this comment.
Made it a constant.
…are detected by content since TIKA-4861
Proof of concept for TIKA-4856, restructured after the discussion in the ticket. The core is the thumbnail defaults and the switch that applies them to the existing endpoints; that is what a client needs to get a document's thumbnail without knowing parser component names. The
/unpack/thumbnailendpoint is a convenience on top and can be dropped or reshaped without losing the rest. The shape of the switch (query parameter) and of the config block (top-level key) are open to change.Why
The thumbnail of a document is one of its embedded documents, typed
THUMBNAIL, and/rmetalists it already. Where a raster image only exists after rendering (the first page of a PDF, the EMF/WMF thumbnail of an Office document), a request needs a parse context that knows the component names, and that context should be the same for every caller.Thumbnail defaults
ThumbnailDefaults(tika-server-core) holds that context in one place: first PDF page rendered at 96 dpi (maxRenderedPages: 1, so the text is still extracted from the whole document), EMF/WMF thumbnail rendered (that one only,renderOnlyEmbeddedResourceTypes: ["THUMBNAIL"]from #3095).Three layers, each overriding the one before: built-in defaults, a
thumbnail-defaultsblock in the server config (same shape as a request config), the request's ownconfigpart. The defaults are plain JSON parser configurations set withParseContext.setJsonConfig, so a parser that is not installed never reads them.?renderThumbnails=trueOn
/rmeta,/unpack,/unpack/alland/unpack/thumbnail: lays the defaults under the request. Without it a parse is the cheap extraction of stored thumbnails; rendering is opt-in, with the same switch everywhere. The index request of a search service becomes/rmeta/text?renderThumbnails=true: metadata, text, and the thumbnail with its dimensions in one parse./unpack/thumbnail(optional)What only makes sense when the thumbnail is all the caller wants (no text extraction, no OCR, only THUMBNAIL and RENDERING extracted, image capped at 32 MiB), plus the defaults when
renderThumbnails=true; a PDF without the switch answers 204.ThumbnailSelectorpicks the raster THUMBNAIL below the document, the rendering below a vector THUMBNAIL, or the first page RENDERING, and answers as JSON:PDFParserConfig.maxRenderedPagesBounds the page rendering of both rendering strategies independently of
maxPages; without it/rmetacould only render the first page by also cutting the text after it.Verified
Against a server built from main plus the open thumbnail PRs: docx, xlsx, doc, xls, ppt, pptx, odt, epub, GeoGebra, Pages, Numbers, Keynote, mp3, m4a, flac, ogg, pdf, nef and pef answer with the right image; a zip, a plain jpeg and a doc without a thumbnail answer 204. Raw camera files no longer need their file name since #3099.
Open points
thumbnail-defaultsis a top-level config key, which meant adding it to the known keys inTikaJsonConfig(tika-serialization). Putting it underserverwould avoid that at the cost of a field in the server config class; fine either way.embedded-limits.maxDepthis 3 in the fixed context because of TIKA-4857, 2 once that is fixed.https://issues.apache.org/jira/browse/TIKA-4856