国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Spring Boot 整合 Apache Tika 實現文件類型檢測與內容提取

開發 前端
在實際開發中,我們經常需要處理各類文件(如PDF、Word、Excel、圖片等),核心需求包括識別文件真實類型(避免后綴名欺騙)和提取文件內容/元數據(如文檔正文、創建時間、作者)。Apache Tika作為Apache基金會的開源項目,能高效解決這些問題,且無需手動編寫不同格式的解析邏輯。

前言

在實際開發中,我們經常需要處理各類文件(如PDF、Word、Excel、圖片等),核心需求包括識別文件真實類型(避免后綴名欺騙)和提取文件內容/元數據(如文檔正文、創建時間、作者)。Apache Tika作為Apache基金會的開源項目,能高效解決這些問題,且無需手動編寫不同格式的解析邏輯。

核心概念

在整合前,先明確Tika3個核心組件,理解其工作原理:

  • Detector(檢測器):負責識別文件的真實類型,支持通過文件頭、字節流、擴展名等多維度檢測,避免 “后綴名篡改” 導致的類型誤判。
  • Parser(解析器):根據Detector識別的文件類型,調用對應的解析器提取文件內容(如文本)和元數據(如文件大小、修改時間),Tika內置了PDF、Office、XML等格式的解析器。
  • Metadata(元數據):存儲文件的結構化信息,分為內置元數據(如Metadata.CONTENT_ENCODINGMetadata.CONTENT_TYPE)和自定義元數據(如文檔作者、版本號)。

案例

依賴添加

Tika依賴較多解析庫(如POI、PDFBox),可能與項目中已有的依賴沖突(如POI版本不一致),手動排除即可。

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>2.9.2</version>
</dependency>

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers-standard-package</artifactId>
    <version>2.9.2</version>
</dependency>

配置 Tika Bean

為避免重復創建Tika實例(提升性能),支持自定義配置(如超時時間、解析器優先級):

@Configuration
public class TikaSelfConfig {

    /**
     * 全局Tika實例(用于文件類型檢測)
     */
    @Bean
    public Tika tika() throws TikaException, IOException, SAXException {
        // 自定義Tika配置:設置文件類型檢測超時時間(5秒)
        TikaConfig config = new TikaConfig();
        return new org.apache.tika.Tika(config) {
            @Override
            public String detect(java.io.InputStream stream, Metadata metadata) {
                try {
                    // 超時控制:避免解析超大文件阻塞
                    return super.detect(new TimeoutInputStream(stream, 5000), metadata);
                } catch (IOException e) {
                    throw new RuntimeException("文件類型檢測超時(超過5秒)", e);
                }
            }
        };
    }

    /**
     * 自動檢測解析器(用于內容提取)
     */
    @Bean
    public Parser autoDetectParser() {
        // AutoDetectParser會根據文件類型自動選擇解析器
        return new AutoDetectParser();
    }

    // 注冊自定義解析器(在TikaConfig中添加)
    @Bean
    public Parser customParser() {
        return new CustomCsvParser();
    }
}


public class TimeoutInputStream extends InputStream {
    private final InputStream delegate;
    private final long timeoutMillis;
    private long lastReadTime;

    public TimeoutInputStream(InputStream delegate, long timeoutMillis) {
        this.delegate = delegate;
        this.timeoutMillis = timeoutMillis;
        this.lastReadTime = System.currentTimeMillis();
    }

    @Override
    public int read() throws IOException {
        checkTimeout();
        int data = delegate.read();
        if (data != -1) {
            lastReadTime = System.currentTimeMillis();
        }
        return data;
    }

    private void checkTimeout() throws IOException {
        long elapsed = System.currentTimeMillis() - lastReadTime;
        if (elapsed > timeoutMillis) {
            throw new IOException("Stream read timeout (elapsed: " + elapsed + "ms)");
        }
    }

    // 重寫其他read方法(read(byte[]), read(byte[], int, int)),邏輯類似
}

功能 1:文件類型檢測

@Service
public class TikaFileDetectService {

    private final Tika tika;

    // 注入全局Tika Bean
    public TikaFileDetectService(Tika tika) {
        this.tika = tika;
    }

    /**
     * 1. 基于MultipartFile(文件流)檢測真實類型(推薦)
     * @param file 上傳的文件
     * @return 真實MIME類型(如image/jpeg、application/pdf)
     */
    public String detectFileByStream(MultipartFile file) throws IOException {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件不能為空");
        }

        // 元數據:可添加文件名輔助檢測(非必需,但能提升準確率)
        Metadata metadata = new Metadata();
        metadata.add(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());

        // 通過文件流檢測(Tika會讀取文件頭字節,不依賴后綴名)
        try (InputStream inputStream = file.getInputStream()) {
            return tika.detect(inputStream, metadata);
        }
    }

    /**
     * 2. 基于字節數組檢測(適用于小文件/內存中的文件)
     * @param bytes 文件字節數組
     * @param fileName 文件名(輔助檢測)
     * @return 真實MIME類型
     */
    public String detectFileByBytes(byte[] bytes, String fileName) {
        if (bytes == null || bytes.length == 0) {
            throw new IllegalArgumentException("字節數組不能為空");
        }

        return tika.detect(bytes, Metadata.TIKA_MIME_FILE);
    }

    /**
     * 3. 基于擴展名檢測(僅作輔助,準確率低)
     * @param fileName 文件名(如test.pdf)
     * @return 推測的MIME類型
     */
    public String detectFileByExtension(String fileName) {
        return tika.detect(fileName);
    }
}

功能 2:文件內容與元數據提取

@Service
public class TikaContentExtractService {

    private final Parser autoDetectParser;

    // 注入自動檢測解析器
    public TikaContentExtractService(Parser autoDetectParser) {
        this.autoDetectParser = autoDetectParser;
    }

    /**
     * 提取文件的文本內容(支持PDF、Word、Excel等)
     * @param file 上傳的文件
     * @return 提取的純文本
     */
    public String extractText(MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new IllegalArgumentException("文件不能為空");
        }

        // 1. 內容處理器:BodyContentHandler用于接收文本內容,設置容量(避免大文件OOM)
        ContentHandler contentHandler = new BodyContentHandler(10 * 1024 * 1024); // 10MB上限

        // 2. 元數據:存儲文件的結構化信息
        Metadata metadata = new Metadata();
        metadata.add(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());

        // 3. 解析上下文:用于傳遞解析器所需的額外信息(如密碼,適用于加密文件)
        ParseContext parseContext = new ParseContext();
        parseContext.set(Parser.class, autoDetectParser); // 綁定當前解析器

        // 4. 解析文件并提取內容
        try (InputStream inputStream = file.getInputStream()) {
            autoDetectParser.parse(inputStream, contentHandler, metadata, parseContext);
            return contentHandler.toString();
        }
    }

    /**
     * 提取文件的元數據(如創建時間、作者、文件大小)
     * @param file 上傳的文件
     * @return 元數據鍵值對(格式化輸出)
     */
    public String extractMetadata(MultipartFile file) throws Exception {
        Metadata metadata = new Metadata();
        ParseContext parseContext = new ParseContext();
        parseContext.set(Parser.class, autoDetectParser);

        try (InputStream inputStream = file.getInputStream()) {
            autoDetectParser.parse(inputStream, new BodyContentHandler(), metadata, parseContext);
        }

        // 格式化元數據輸出(遍歷所有元數據鍵)
        StringBuilder metadataStr = new StringBuilder();
        for (String name : metadata.names()) {
            metadataStr.append(name).append(": ").append(metadata.get(name)).append("\n");
        }
        return metadataStr.toString();
    }


    /**
     * 提取加密文件的文本內容(支持PDF、Word、Excel等)
     * @param file 上傳的文件
     * @return 提取的純文本
     * 1. 對舊版 Office 文檔(.doc、.xls),使用 POI 的 EncryptionInfo 和 Decryptor 直接解密
     * 2. 對新版 Office 文檔(.docx、.xlsx),仍使用 Tika 的 PasswordProvider
     */
    public String extractEncryptedText(MultipartFile file, String password) throws Exception {
        ContentHandler handler = new BodyContentHandler();
        Metadata metadata = new Metadata();
        metadata.add(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename());
        metadata.set("password", password);

        AutoDetectParser autoDetectParser = new AutoDetectParser();
        ParseContext context = new ParseContext();
        context.set(PasswordProvider.class,metadata1 -> password);
        try (InputStream inputStream = file.getInputStream()) {
            autoDetectParser.parse(inputStream, handler, metadata, context);
            return handler.toString();
        }
    }
}

功能 3:自定義解析器

// 自定義解析器:處理.csv格式文件(示例,Tika已內置CSV解析器,此處僅演示擴展)
public class CustomCsvParser extends AbstractParser {

    // 聲明支持的MIME類型
    @Override
    public Set<MediaType> getSupportedTypes(ParseContext context) {
        return Collections.singleton(MediaType.parse("text/csv"));
    }

    // 核心解析邏輯
    @Override
    public void parse(InputStream stream, ContentHandler handler, Metadata metadata, ParseContext context)
            throws IOException, SAXException {
        // 1. 設置CSV文件的元數據
        metadata.add("file_format", "CSV");
        metadata.add("delimiter", ",");

        // 2. 讀取CSV內容并寫入ContentHandler
        String csvContent = readInputStreamAsString(stream);
        handler.characters(csvContent.toCharArray(), 0, csvContent.length());
    }

    private String readInputStreamAsString(InputStream inputStream) throws IOException {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int nRead;
        byte[] data = new byte[1024];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        buffer.flush();
        return new String(buffer.toByteArray(), StandardCharsets.UTF_8);
    }
}

測試代碼

圖片圖片

@Test
    public void tikaFile() throws Exception {
        File fakeImageFile = new File("D:\\文檔\\自動巡檢腳本部署說明.docx");
        MultipartFile mockFile = new MockMultipartFile("file",new FileInputStream(fakeImageFile));
        System.out.println(tikaContentExtractService.extractText(mockFile));
        System.out.println(tikaContentExtractService.extractMetadata(mockFile));
//        System.out.println(tikaContentExtractService.extractEncryptedText(mockFile,"123456"));
    }


責任編輯:武曉燕 來源: 一安未來
相關推薦

2025-01-02 11:01:13

Apache文件類型部署

2025-03-31 08:43:34

SpringTika優化

2025-09-10 09:31:04

2017-04-17 10:35:40

Spring BooRedis 操作

2009-11-16 12:17:46

PHP上傳文件類型

2025-09-08 04:07:00

SpringApache工具

2024-10-31 09:42:08

2022-08-24 08:42:59

Minio存儲Golang

2024-10-14 13:26:42

2009-08-12 16:44:13

.NET文件類型

2023-10-12 10:32:51

2010-03-10 09:27:36

Linux鏈接文件類型

2010-01-05 15:32:33

2010-03-01 15:34:38

Linux文件類型

2024-11-11 10:02:37

Spring搜索數據

2025-03-26 03:25:00

SpringGuavaCaffeine

2025-07-02 07:33:02

Spring倒排索引分布式

2022-12-23 08:28:42

策略模式算法

2025-05-09 07:20:02

Spring數據庫檢索

2009-10-21 10:50:59

Linux文件類型
點贊
收藏

51CTO技術棧公眾號

日精品一区二区| 日韩欧美国产视频| 久久99影院| 色婷婷久久久| 中文字幕无线精品亚洲乱码一区| 91精品久久| 一本到不卡精品视频在线观看| 激情丁香婷婷| 国产精品午夜电影| 成人在线免费在线观看| 麻豆精品新av中文字幕| 色播亚洲视频在线观看| 鲁大师成人一区二区三区| 久久国产手机看片| 亚洲欧美视频一区二区三区| 国产欧美日韩一区二区三区| 欧美日韩网址| 九九热最新视频//这里只有精品| 97热精品视频官网| 亚洲国产精品一区二区久久恐怖片| 水蜜桃在线免费观看| 另类综合日韩欧美亚洲| 日韩精品欧美在线| 日本美女一区二区| 无码人妻精品一区二区三区99v| 蜜臀久久久99精品久久久久久| 色狠狠久久av五月综合|| 免费精品99久久国产综合精品| 一区二区三区四区五区视频 | 宅男噜噜噜66一区二区66| yw在线观看| 日韩欧美国产一区二区在线播放| 肉体视频在线| 中文字幕在线观看亚洲| 国产成人av毛片| 国产一区视频在线播放| 亚洲精品美女91| 最新不卡av| 久久久久国产免费免费| 特黄特黄的视频| 欧美美女视频在线观看| 99thz桃花论族在线播放| 北条麻妃99精品青青久久| 啪啪激情综合网| 69堂成人精品视频免费| 日韩国产精品久久久久久亚洲| 欧美国产视频一区| 亚洲免费在线观看视频| 男人的天堂在线视频免费观看| 亚洲精品99久久久久中文字幕| 亚洲电影有码| 日本sm极度另类视频| 精品白丝av| 色欲色香天天天综合网www| 一区二区在线免费| 四虎影视国产在线视频| 久久久久久69| 亚洲黄色精品| 粉嫩虎白女毛片人体| 一片黄亚洲嫩模| 超碰在线视屏| 国产精品美女av| 美腿丝袜亚洲三区| 天美星空大象mv在线观看视频| 亚洲成人动漫精品| 久草在线中文最新视频| 国产69精品久久久久99| 国产欧美一区二区色老头| 国产精品亚洲a| 欧美日韩情趣电影| 亚洲精品18| 久久久久资源| 亚洲欧美日韩中文播放 | 国产一区二区在线视频你懂的| 亚洲综合中文字幕在线观看| 99re在线视频这里只有精品| 97人人在线| 午夜精品久久久久久久99热| 麻豆九一精品爱看视频在线观看免费| 精品免费国产一区二区| 欧美一区二区三区免费在线看 | 久久精品国产v日韩v亚洲| 欧美3p视频| 欧美日韩亚洲一| 日韩一区二区高清| 欧美日韩第一| 亚洲欧洲日产国码无码久久99| 欧美一区二区视频免费观看| 蜜桃视频欧美| 欧美国产亚洲一区| 欧美成人一区二区三区片免费| jiujiure精品视频播放| 免费毛片小视频| 亚洲精品久久久一区二区三区| 欧美日本精品| 97视频免费| 久久成人精品视频| 国产高清精品在线| 欧美xxxx少妇| 激情小说综合区| 午夜精品在线看| 台湾色综合娱乐中文网| www黄色日本| 国产香蕉精品视频一区二区三区| 99综合在线| 成人高清在线| 成人免费xxxxx在线观看| ㊣最新国产の精品bt伙计久久| 3d动漫一区二区三区在线观看| 浴室偷拍美女洗澡456在线| 日韩一区二区在线看片| 888久久久| 特黄特色特刺激视频免费播放 | 欧美日韩国产中字| 九色丨蝌蚪丨成人| 97xxxxx| 伊人久久久久久久久久| 精品综合免费视频观看| 一二三四区在线观看| 国产日韩精品久久| 欧美中文字幕亚洲一区二区va在线 | 亚洲精品在线免费看| 欧美男人的天堂一二区| 狠狠色丁香久久综合频道| 中文字幕在线影视资源| 国产精品黄视频| 亚洲精品中文在线影院| 亚洲电影一级片| 日本福利小视频| 国产精品久久久久久搜索| 亚洲精品五月天| 久久影院资源站| 久久精品无码一区二区日韩av| 国模吧一区二区三区| 亚洲国产成人在线| 亚洲a级精品| 亚洲激情文学| 99精彩视频| 51久久夜色精品国产麻豆| 丝袜亚洲精品中文字幕一区| 超碰在线99| 国产熟女高潮视频| 热久久免费视频精品| 婷婷一区二区三区| 国产精品久久久免费| aa国产成人| 国产免费视频传媒| 国产女同一区二区| 欧美日韩一区二区三区高清| 免费视频一区| 我爱我色成人网| 色视频www在线播放国产人成| 91精品久久久久久久久久| 5566中文字幕一区二区电影| 极品美女销魂一区二区三区| 91麻豆精品国产综合久久久| h片免费观看| 国产精品国产三级国产专区53| 精品国产制服丝袜高跟| 成人av免费观看| 亚洲人成亚洲精品| 69xxxx欧美| www.浪潮av.com| 成人国产在线视频| 日韩欧美自拍偷拍| 久久午夜国产精品| 欧美一区二区三| 手机电影在线观看| 国产一级特黄a大片免费| 91久久精品日日躁夜夜躁国产| 精品久久久网站| 久久久www成人免费无遮挡大片| 日本a口亚洲| 国产探花在线观看| 欧美激情国产精品日韩| 成人伊人精品色xxxx视频| 日韩精品在线影院| 亚洲精品网站在线观看| 老牛影视一区二区三区| 中文字幕av一区二区三区四区| 亚洲最大成人网4388xx| 自拍偷拍亚洲欧美日韩| 亚洲女同中文字幕| 久久99精品久久久久久久青青日本| 精品国产免费视频| 国产午夜亚洲精品理论片色戒| 国产精品97| 欧美日韩亚洲国产| 亚洲女人天堂| 免费看欧美一级片| 免费成人动漫| 999成人精品视频线3| 久久不射网站| 伊人久久国产| 色老板在线视频| 在线观看日本一区| 国产精品免费久久久久久| 亚洲欧洲自拍偷拍| 亚洲成人久久影院| 成人免费黄色在线|