Apache Tika提取DOCX嵌入写字板文件转为.bin问题求助
解决Tika提取DOCX中嵌入写字板文件变为OleObject.bin的问题
我之前也碰到过类似的困扰——用Tika的示例代码提取嵌入文件时,写字板文件总是被存成OleObject.bin,完全丢失了原始格式和公式内容。后来研究了Tika处理OLE对象的逻辑,找到了几个可行的解决方案:
1. 从元数据中获取原始文件名/类型,指定正确扩展名
Tika在解析嵌入OLE对象时,其实会把原始文件名、内容类型等信息存在元数据里。你可以在保存文件前读取这些元数据,替换默认的.bin扩展名:
// 在处理嵌入文档的逻辑中(参考ExtractEmbeddedFiles.java的processEmbedded方法) int count = 0; // 用于区分多个嵌入文件 File outputDir = new File("你的输出文件夹路径"); // 获取嵌入文档的元数据 Metadata metadata = new Metadata(); EmbeddedDocumentExtractor extractor = parser.getEmbeddedDocumentExtractor(metadata); if (extractor.shouldParseEmbedded(metadata)) { try (InputStream embeddedStream = extractor.getEmbeddedStream(metadata)) { String fileName = null; // 优先取原始文件名 String originalFileName = metadata.get(Metadata.ORIGINAL_FILE_NAME); if (originalFileName != null) { fileName = originalFileName; } else { // 若没有原始文件名,根据OLE类名或内容类型推断 String oleClassName = metadata.get("OLE2_CLASS_NAME"); String contentType = metadata.get(Metadata.CONTENT_TYPE); if ("WordPad.Document.1".equals(oleClassName) || "Write.Document.1".equals(oleClassName)) { fileName = "embedded_writedoc_" + count + ".rtf"; // 写字板通常存为RTF格式 } else if ("text/rtf".equals(contentType)) { fileName = "embedded_rtf_" + count + ".rtf"; } else { // fallback到默认命名 fileName = "OleObject_" + count + ".bin"; } } // 保存文件 File outputFile = new File(outputDir, fileName); Files.copy(embeddedStream, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING); count++; } }
2. 针对写字板OLE对象单独解析内容
有些写字板文件是OLE容器包裹的RTF内容,你可以用Tika的OLE解析器直接提取内部的原始内容,而不是保存整个OLE二进制文件:
// 当检测到是写字板OLE对象时 if ("application/vnd.ms-office.oleobject".equals(metadata.get(Metadata.CONTENT_TYPE))) { String oleClassName = metadata.get("OLE2_CLASS_NAME"); if ("WordPad.Document.1".equals(oleClassName)) { try (InputStream oleStream = extractor.getEmbeddedStream(metadata)) { // 使用Tika解析OLE流,获取RTF内容 Tika tika = new Tika(); String rtfContent = tika.parseToString(oleStream); // 保存为RTF文件 File rtfFile = new File(outputDir, "wordpad_doc_" + count + ".rtf"); try (FileWriter writer = new FileWriter(rtfFile)) { writer.write(rtfContent); } count++; continue; // 跳过默认的.bin保存逻辑 } catch (Exception e) { e.printStackTrace(); } } }
3. 确保依赖完整,避免解析缺失
如果你的项目缺少POI的Scratchpad模块,Tika可能无法正确识别写字板OLE对象。如果用Maven,记得添加以下依赖:
<dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-core</artifactId> <version>你的Tika版本(比如2.9.1)</version> </dependency> <dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-parsers-standard-package</artifactId> <version>你的Tika版本</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-scratchpad</artifactId> <version>对应POI版本(和Tika依赖的POI版本一致)</version> </dependency>
核心思路就是:通过元数据识别嵌入对象的真实类型,针对写字板文件做特殊处理,要么直接用原始文件名保存,要么解析OLE容器提取内部的RTF内容,这样就能保留原始格式和公式了。
内容的提问来源于stack exchange,提问作者SakshamB
相关产品推荐
相关产品推荐

