You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Tika 2.4.1添加自定义Detector的正确方法及异常解决

Apache Tika 2.4.1 自定义SVG检测器的正确实现方法

问题根源

你直接通过new Tika(new SvgDetector())初始化Tika实例时,会替换掉默认的所有检测器集合,只保留自定义的SVG检测器。当检测非SVG文件(如.png)时,自定义检测器返回null,后续调用toString()就会触发空指针异常。

正确实现方案

方案1:组合自定义检测器与默认检测器集合

将自定义SVG检测器添加到Tika默认的检测器列表中,这样既保留原有检测能力,又能识别SVG文件:

import org.apache.tika.Tika;
import org.apache.tika.detect.CompositeDetector;
import org.apache.tika.detect.Detector;
import org.apache.tika.config.TikaConfig;
import java.util.ArrayList;
import java.util.List;

// 获取Tika默认的检测器集合
Detector defaultDetector = TikaConfig.getDefaultConfig().getDetector();

// 组合自定义检测器与默认检测器
List<Detector> detectors = new ArrayList<>();
detectors.add(new SvgDetector());
detectors.add(defaultDetector);
CompositeDetector compositeDetector = new CompositeDetector(detectors);

// 使用组合后的检测器创建Tika实例
Tika tika = new Tika(compositeDetector);
String mimeTypeValue = tika.detect(multipartFile.getInputStream());

优化自定义SvgDetector的实现

原检测器存在两个问题:一是读取整个输入流会导致流耗尽,影响后续处理;二是检测逻辑过于严格(要求首尾严格匹配<svg>和</svg>),容易误判。优化后的实现如下:

import org.apache.tika.detect.Detector;
import org.apache.tika.io.MarkableInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class SvgDetector implements Detector {
    private static final MediaType SVG_TYPE = MediaType.parse("image/svg+xml");
    // 仅读取文件前1024个字符做检测,避免耗尽流
    private static final int MAX_READ_LENGTH = 1024;

    @Override
    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
        MarkableInputStream markableInput = new MarkableInputStream(input);
        try {
            // 标记当前流位置,后续可重置
            markableInput.mark(MAX_READ_LENGTH);
            
            byte[] buffer = new byte[MAX_READ_LENGTH];
            int actualRead = markableInput.read(buffer);
            String contentPrefix = new String(buffer, 0, actualRead, StandardCharsets.UTF_8).toLowerCase();
            
            // 宽松检测SVG标签(兼容带命名空间的情况,如<svg xmlns="http://www.w3.org/2000/svg">)
            if (contentPrefix.contains("<svg")) {
                return SVG_TYPE;
            }
            return null;
        } finally {
            // 重置流位置,确保后续检测器能正常读取
            markableInput.reset();
        }
    }
}

方案2:在自定义检测器中委托默认检测

如果不想手动组合检测器,也可以在自定义检测器中先尝试SVG检测,未命中时委托给默认检测器:

import org.apache.tika.detect.Detector;
import org.apache.tika.io.MarkableInputStream;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.mime.MediaType;
import org.apache.tika.config.TikaConfig;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

public class SvgDetector implements Detector {
    private final Detector defaultDetector = TikaConfig.getDefaultConfig().getDetector();
    private static final MediaType SVG_TYPE = MediaType.parse("image/svg+xml");
    private static final int MAX_READ_LENGTH = 1024;

    @Override
    public MediaType detect(InputStream input, Metadata metadata) throws IOException {
        MarkableInputStream markableInput = new MarkableInputStream(input);
        try {
            markableInput.mark(MAX_READ_LENGTH);
            byte[] buffer = new byte[MAX_READ_LENGTH];
            int actualRead = markableInput.read(buffer);
            String contentPrefix = new String(buffer, 0, actualRead, StandardCharsets.UTF_8).toLowerCase();
            
            if (contentPrefix.contains("<svg")) {
                return SVG_TYPE;
            }
            // 未命中SVG,委托给默认检测器
            markableInput.reset();
            return defaultDetector.detect(markableInput, metadata);
        } finally {
            markableInput.reset();
        }
    }
}

此时直接使用new Tika(new SvgDetector())初始化即可,无需额外组合检测器。

内容的提问来源于stack exchange,提问作者SageJustus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 19:39:28