001/* 002 * Copyright (c) 2023-2026, Agents-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.agentsflex.core.file2text.extractor.impl; 017 018import com.agentsflex.core.file2text.extractor.FileExtractor; 019import com.agentsflex.core.file2text.source.DocumentSource; 020import org.apache.poi.hwpf.HWPFDocument; 021import org.apache.poi.hwpf.extractor.WordExtractor; 022import org.apache.poi.poifs.filesystem.POIFSFileSystem; 023 024import java.io.IOException; 025import java.io.InputStream; 026import java.util.Collections; 027import java.util.HashSet; 028import java.util.Set; 029 030/** 031 * DOC 文档提取器(.doc) 032 * 支持旧版 Word 97-2003 格式 033 */ 034public class DocExtractor implements FileExtractor { 035 036 private static final Set<String> SUPPORTED_MIME_TYPES; 037 private static final Set<String> SUPPORTED_EXTENSIONS; 038 039 static { 040 Set<String> mimeTypes = new HashSet<>(); 041 mimeTypes.add("application/msword"); 042 SUPPORTED_MIME_TYPES = Collections.unmodifiableSet(mimeTypes); 043 044 Set<String> extensions = new HashSet<>(); 045 extensions.add("doc"); 046 extensions.add("dot"); 047 SUPPORTED_EXTENSIONS = Collections.unmodifiableSet(extensions); 048 } 049 050 @Override 051 public boolean supports(DocumentSource source) { 052 String mimeType = source.getMimeType(); 053 String fileName = source.getFileName(); 054 055 if (mimeType != null && SUPPORTED_MIME_TYPES.contains(mimeType)) { 056 return true; 057 } 058 059 if (fileName != null) { 060 String ext = getExtension(fileName); 061 if (ext != null && SUPPORTED_EXTENSIONS.contains(ext.toLowerCase())) { 062 return true; 063 } 064 } 065 066 return false; 067 } 068 069 @Override 070 public String extractText(DocumentSource source) throws IOException { 071 try (InputStream is = source.openStream(); 072 POIFSFileSystem fs = new POIFSFileSystem(is); 073 HWPFDocument doc = new HWPFDocument(fs)) { 074 075 WordExtractor extractor = new WordExtractor(doc); 076 String[] paragraphs = extractor.getParagraphText(); 077 078 StringBuilder text = new StringBuilder(); 079 for (String para : paragraphs) { 080 // 清理控制字符 081 String clean = para.replaceAll("[\\r\\001]+", "").trim(); 082 if (!clean.isEmpty()) { 083 text.append(clean).append("\n"); 084 } 085 } 086 return text.toString().trim(); 087 } catch (Exception e) { 088 throw new IOException("Failed to extract .doc file: " + e.getMessage(), e); 089 } 090 } 091 092 @Override 093 public int getOrder() { 094 return 15; // 低于 .docx 095 } 096 097 private String getExtension(String fileName) { 098 if (fileName == null || !fileName.contains(".")) return null; 099 int lastDot = fileName.lastIndexOf('.'); 100 return fileName.substring(lastDot + 1); 101 } 102}