[
https://issues.apache.org/jira/browse/TIKA-4856?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18109542#comment-18109542
]
ASF GitHub Bot commented on TIKA-4856:
--------------------------------------
dschmidt commented on code in PR #3096:
URL: https://github.com/apache/tika/pull/3096#discussion_r3887677664
##########
tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java:
##########
@@ -215,15 +272,162 @@ public Response unpackAll(InputStream is, @Context
HttpHeaders httpHeaders, @Con
@POST
@Consumes("multipart/form-data")
@Produces("application/zip")
- public Response unpackAllWithConfig(List<Attachment> attachments, @Context
HttpHeaders httpHeaders, @Context UriInfo info) throws Exception {
+ public Response unpackAllWithConfig(List<Attachment> attachments, @Context
HttpHeaders httpHeaders, @Context UriInfo info,
+ @QueryParam("renderThumbnails") boolean
renderThumbnails) throws Exception {
ParseContext pc = tikaResource.createRequestContext();
Metadata metadata = tikaResource.newRequestMetadata();
try (TikaInputStream tis =
tikaResource.setupMultipartConfig(attachments, metadata, pc)) {
TikaResource.logRequest(LOG, "/unpack/all", metadata);
+ if (renderThumbnails) {
+ //under the request's config, which setupMultipartConfig has
already merged
+ tikaResource.getThumbnailDefaults().applyTo(pc);
+ }
return doUnpack(tis, metadata, pc, true);
}
}
+ /**
+ * Returns the document thumbnail with its metadata (simple PUT).
+ */
+ @jakarta.ws.rs.Path("/thumbnail")
+ @PUT
+ @Produces("application/json")
+ public Response unpackThumbnail(InputStream is, @Context HttpHeaders
httpHeaders) throws Exception {
+ ParseContext pc = tikaResource.createRequestContext();
+ Metadata metadata = tikaResource.newRequestMetadata();
+ try (TikaInputStream tis = TikaInputStream.get(is)) {
+ fillMetadata(null, metadata, httpHeaders.getRequestHeaders());
+ TikaResource.logRequest(LOG, "/unpack/thumbnail", metadata);
+ return doUnpackThumbnail(tis, metadata, pc);
+ }
+ }
+
+ /**
+ * Returns the document thumbnail with its metadata (multipart POST,
"file" part).
+ */
+ @jakarta.ws.rs.Path("/thumbnail")
+ @POST
+ @Consumes("multipart/form-data")
+ @Produces("application/json")
+ public Response unpackThumbnailMultipart(List<Attachment> attachments,
@Context HttpHeaders httpHeaders)
+ throws Exception {
+ ParseContext pc = tikaResource.createRequestContext();
+ Metadata metadata = tikaResource.newRequestMetadata();
+ try (TikaInputStream tis =
tikaResource.setupMultipartConfig(attachments, metadata, pc)) {
+ TikaResource.logRequest(LOG, "/unpack/thumbnail", metadata);
+ return doUnpackThumbnail(tis, metadata, pc);
+ }
+ }
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+ private static final String METADATA_SUFFIX = ".metadata.json";
+
+ /**
+ * Parses in unpack mode with the thumbnail configuration, then selects
+ * the thumbnail among the extracted embedded documents.
+ */
+ private Response doUnpackThumbnail(TikaInputStream tis, Metadata metadata,
ParseContext pc)
+ throws Exception {
+ PipesParsingHelper helper = tikaResource.getPipesParsingHelper();
+ if (helper == null) {
+ throw new WebApplicationException("Pipes-based parsing is not
enabled", Response.Status.SERVICE_UNAVAILABLE);
+ }
+ configureThumbnailParse(pc);
+
+ PipesParsingHelper.UnpackResult result = helper.parseUnpack(tis,
metadata, pc, false);
+ if (result.zipFile() == null) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+ try (ZipFile zip = new ZipFile(result.zipFile().toFile())) {
+ Map<String, Metadata> extracted = readExtractedMetadata(zip);
+ Metadata thumbnail = ThumbnailSelector.select(new
ArrayList<>(extracted.values()));
+ if (thumbnail == null) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+ String entryName = null;
+ for (Map.Entry<String, Metadata> e : extracted.entrySet()) {
+ if (e.getValue() == thumbnail) {
+ entryName = e.getKey();
+ }
+ }
+ ZipEntry imageEntry = entryName == null ? null :
zip.getEntry(entryName);
+ if (imageEntry == null) {
+ throw new WebApplicationException(Response.Status.NO_CONTENT);
+ }
+ byte[] image;
+ try (InputStream is = zip.getInputStream(imageEntry)) {
+ image = is.readAllBytes();
+ }
Review 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.
> /unpack/thumbnail: return the document thumbnail with its metadata
> ------------------------------------------------------------------
>
> Key: TIKA-4856
> URL: https://issues.apache.org/jira/browse/TIKA-4856
> Project: Tika
> Issue Type: New Feature
> Reporter: Dominik Schmidt
> Priority: Major
>
> With TIKA-4850 through TIKA-4855 every container format that carries a
> thumbnail emits it as a THUMBNAIL embedded document, the PDF parser renders
> pages as RENDERING documents, and the EMF/WMF renderer turns the vector
> thumbnails of Office documents into raster ones. Getting "the thumbnail of
> this file" out of that still takes format knowledge on the client: the
> THUMBNAIL of a Word or Excel file is an EMF/WMF whose usable form is the
> RENDERING underneath it, a PDF has no THUMBNAIL but a page RENDERING, the
> THUMBNAIL of a DOCX inside a ZIP is not the ZIP's, and with rendering enabled
> the picture of an embedded OLE object is a RENDERING too. Plus the request
> config that switches the renderers on.
> Proposal: POST /unpack/thumbnail next to /unpack and /unpack/all, multipart
> like them. It runs the usual forked parse in unpack mode with a fixed parse
> context (PDF page 1 rendered, EMF/WMF rendered) and picks, in this order: the
> raster THUMBNAIL at depth 1; the rendering of that thumbnail; the depth-1
> RENDERING of PDF page 1. The endpoint extracts what the document carries; it
> does not resize, convert or generate previews.
> The response is JSON: the /rmeta metadata object of the selected embedded
> document, and the image as base64. Thumbnails are small, so the encoding
> overhead does not matter, and the caller gets type, dimensions, origin
> (stored thumbnail or rendering, tk:rendering:rendered-by) and path in one
> round trip without unpacking a zip. 204 when the document has no thumbnail.
> {
> "metadata": {
> "Content-Type": "image/png",
> "Content-Length": "8459",
> "tiff:ImageWidth": "800",
> "tiff:ImageLength": "1131",
> "tk:embedded-resource-type": "RENDERING",
> "tk:embedded-resource-path": "/thumbnail.emf/thumbnail.png",
> "tk:embedded-depth": "2",
> "tk:rendering:rendered-by": "poi-metafile-renderer",
> "tk:resource-name": "thumbnail.png"
> },
> "image": "iVBORw0KGgoAAAANSUhEUgAA..."
> }
> To keep the selection rule short, the metafile renderer could give the
> rendering of a THUMBNAIL the THUMBNAIL type as well (its
> tk:rendering:rendered-by tells it apart), so a raster thumbnail is a
> THUMBNAIL regardless of whether the document stored it as PNG or as EMF.
> What do you think?
--
This message was sent by Atlassian Jira
(v8.20.10#820010)