java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java判断文件类型

java不依赖后缀名判断上传文件的类型的两种方法

作者:悟能不能悟

在Java中,判断上传文件的类型而不依赖文件后缀名,可以通过分析文件的内容特征来实现,以下是两种常用方法,大家可以根据自己的需求参考

在Java中,判断上传文件的类型而不依赖文件后缀名,可以通过分析文件的内容特征(魔数/Magic Number)​​ 来实现。以下是两种常用方法:

方法一:通过文件头(Magic Number)识别

每种文件类型在文件开头有特定的字节序列(通常称为魔数)。读取文件的前几个字节并与已知类型比对即可。

import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class FileTypeDetector {

    // 常见文件类型的魔数字典(十六进制)
    private static final Map<String, String> MAGIC_NUMBERS = new HashMap<>();
    static {
        MAGIC_NUMBERS.put("FFD8FF", "image/jpeg");      // JPEG
        MAGIC_NUMBERS.put("89504E47", "image/png");     // PNG
        MAGIC_NUMBERS.put("47494638", "image/gif");     // GIF
        MAGIC_NUMBERS.put("25504446", "application/pdf"); // PDF
        MAGIC_NUMBERS.put("504B0304", "application/zip"); // ZIP或DOCX/XLSX等
        MAGIC_NUMBERS.put("52617221", "application/x-rar-compressed"); // RAR
    }

    public static String detectFileType(byte[] fileBytes) {
        // 将文件前8字节转为十六进制字符串
        StringBuilder hexBuilder = new StringBuilder();
        for (int i = 0; i < Math.min(8, fileBytes.length); i++) {
            hexBuilder.append(String.format("%02X", fileBytes[i] & 0xFF));
        }
        String fileHeader = hexBuilder.toString();

        // 匹配魔数
        for (Map.Entry<String, String> entry : MAGIC_NUMBERS.entrySet()) {
            if (fileHeader.startsWith(entry.getKey())) {
                return entry.getValue();
            }
        }
        return "application/octet-stream"; // 未知类型
    }

    // 示例:从上传的文件读取字节并检测
    public static void main(String[] args) throws IOException {
        String filePath = "uploaded_file.dat"; // 替换为实际文件路径
        try (FileInputStream fis = new FileInputStream(filePath)) {
            byte[] headerBytes = new byte[8];
            int read = fis.read(headerBytes);
            if (read > 0) {
                String mimeType = detectFileType(headerBytes);
                System.out.println("Detected MIME Type: " + mimeType);
            }
        }
    }
}

方法二:使用 Apache Tika 库(推荐)

Apache Tika 是一个强大的内容分析工具,支持超过1000种文件类型的深度检测。

步骤:​

添加 Maven 依赖:

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>2.9.1</version> <!-- 使用最新版本 -->
</dependency>

代码示例:

import org.apache.tika.Tika;
import java.io.File;
import java.io.IOException;

public class TikaFileDetector {
    public static void main(String[] args) throws IOException {
        Tika tika = new Tika();
        File uploadedFile = new File("uploaded_file.dat");

        // 检测MIME类型(基于内容)
        String mimeType = tika.detect(uploadedFile);
        System.out.println("Detected MIME Type: " + mimeType);
    }
}

注意事项

魔数检测的局限性​:

Tika的优势​:

性能考虑​:

大文件只需读取前几KB即可(Tika和魔数方法均如此)。

实际应用场景(Servlet上传示例)

@WebServlet("/upload")
public class FileUploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        Part filePart = request.getPart("file");
        try (InputStream fileStream = filePart.getInputStream()) {
            Tika tika = new Tika();
            
            // 只读取部分内容进行检测(Tika自动优化)
            String mimeType = tika.detect(fileStream);
            
            if (!mimeType.startsWith("image/")) {
                response.sendError(400, "只允许上传图片");
                return;
            }
            // 处理合法文件...
        }
    }
}

结论

简单需求​:使用魔数检测(轻量级)。

生产环境​:优先选择 ​Apache Tika​(准确度高、维护性好)。

永远不要信任客户端提交的文件后缀名或MIME类型声明,服务端必须重新验证内容。

到此这篇关于java不依赖后缀名判断上传文件的类型的两种方法的文章就介绍到这了,更多相关java判断文件类型内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文