1. 概述

本文将探讨在Java中判断文件是否为PDF的多种方法,包括无第三方依赖的原始方案和使用不同库的实现方式。这些方法各有优劣,适用于不同场景。

2. 通过文件签名检测

文件签名(又称魔数)是文件开头用于标识文件类型的字节序列。**PDF文件的签名包含十六进制的25 50 44 46 2D,对应ASCII字符串%PDF-**。

在后续示例中,我们将使用以下常量表示测试用的PDF文件:

final File PDF_FILE = new File("src/test/resources/input.pdf");

通过读取文件前5个字节并与签名匹配即可判断文件类型:

@Test
void whenDetectPdfByFileSignature_thenCorrect() throws IOException {
    boolean isPdf = false;
    try (InputStream fis = new BufferedInputStream(new FileInputStream(PDF_FILE))) {
        byte[] bytes = new byte[5];
        if (fis.read(bytes) == 5) {
            String header = new String(bytes);
            isPdf = Objects.equals(header, "%PDF-");
        }
    }
    assertTrue(isPdf);
}

优势:轻量级实现,无需第三方依赖
局限:仅检查文件头,无法验证文件完整性

3. 使用Apache Tika检测

Apache Tika是开源工具包,提供统一接口检测多种文件类型(包括PDF)。当应用需要识别多种文件格式时特别实用。

添加Maven依赖:

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

通过检测文件的MIME类型判断是否为PDF:

@Test
void whenDetectPdfByTika_thenCorrect() throws IOException {
    Tika tika = new Tika();
    boolean isPdf = Objects.equals(tika.detect(PDF_FILE), "application/pdf");
    assertTrue(isPdf);
}

⚠️ 注意:Tika内部仍基于文件签名检测,但封装了更通用的文件类型识别逻辑

4. 使用Apache PDFBox检测

Apache PDFBox是主流的PDF操作开源库,提供完整的PDF处理功能。

添加Maven依赖:

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>3.0.4</version>
</dependency>

通过尝试加载文件验证PDF有效性:

@Test
void whenDetectPdfByPdfBox_thenCorrect() throws IOException {
    boolean isPdf;
    try (PDDocument document = Loader.loadPDF(PDF_FILE)) {
        isPdf = true;
    } catch (IOException ioe) {
        isPdf = false;
    }
    assertTrue(isPdf);
}

关键点

  • 使用try-with-resources确保资源释放
  • 非PDF文件会抛出IOException

5. 使用iText检测

iText是另一款强大的PDF处理库,适合需要高级PDF操作的场景。

添加Maven依赖:

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.2.4</version>
</dependency>

通过创建PdfDocument对象验证文件:

@Test
void whenDetectPdfByItext_thenCorrect() {
    boolean isPdf;
    try (PdfDocument pdfDoc = new PdfDocument(new PdfReader(PDF_FILE))) {
    isPdf = true;
    } catch (ITextException | IOException e) {
        isPdf = false;
    }
    assertTrue(isPdf);
}

缺点:仅用于文件类型检测时过于重量级,会完整解析文件

6. 方案选择建议

根据实际需求选择合适方案:

场景 推荐方案 理由
仅需检测文件类型 文件签名检测 轻量高效,无依赖
需检测多种文件类型 Apache Tika 统一接口,扩展性强
需操作PDF内容 Apache PDFBox/iText 提供完整PDF处理能力

核心原则

  • ✅ 纯检测场景优先选择文件签名或Tika
  • ✅ 需要PDF操作时直接使用PDFBox/iText
  • ❌ 避免为简单检测引入重量级库

完整示例代码可在GitHub仓库获取。


原始标题:Determine if a File Is a PDF File in Java | Baeldung