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仓库获取。