Java 限制文件上传类型

在 Java 的 Web 后端(如 Spring Boot)中,限制文件上传类型通常通过判断 MultipartFile 的 Content-Type(MIME 类型)或文件扩展名(后缀名)来实现。


一、限制文件类型的常见做法

方法 1:根据 MultipartFile.getContentType() 判断 MIME 类型

java 复制代码
public void validateFileType(MultipartFile file) {
    List<String> allowedTypes = List.of("image/png", "image/jpeg", "application/pdf");
    String contentType = file.getContentType();

    if (!allowedTypes.contains(contentType)) {
        throw new IllegalArgumentException("不支持的文件类型: " + contentType);
    }
}

⚠️ 注意:浏览器伪造 Content-Type 是可能的,因此推荐再结合后缀判断或做文件头检查(Magic Number)


方法 2:根据文件名后缀判断类型(不安全但能挡住大部分无意误传)

java 复制代码
public void validateExtension(MultipartFile file) {
    String filename = file.getOriginalFilename().toLowerCase();
    List<String> allowedExtensions = List.of(".jpg", ".jpeg", ".png", ".pdf");

    if (allowedExtensions.stream().noneMatch(filename::endsWith)) {
        throw new IllegalArgumentException("不支持的文件后缀");
    }
}

方法 3:安全性更高 ------ 检查文件头(Magic Number)

每种文件格式都有"魔数"(Magic Number),可使用第三方库如 Apache TikaJMimeMagicFileTypeDetector 来检测。

使用 Apache Tika 示例:
java 复制代码
import org.apache.tika.Tika;

public void validateByTika(MultipartFile file) throws IOException {
    Tika tika = new Tika();
    String detectedType = tika.detect(file.getInputStream());

    List<String> allowedTypes = List.of("image/jpeg", "image/png", "application/pdf");
    if (!allowedTypes.contains(detectedType)) {
        throw new IllegalArgumentException("文件类型不合法: " + detectedType);
    }
}

二、实战应用整合到上传接口中(Spring Boot)

java 复制代码
@PostMapping("/upload")
public ResponseEntity<?> upload(@RequestParam MultipartFile file) throws IOException {
    validateFileType(file);      // 判断 MIME 类型
    validateExtension(file);     // 判断文件名后缀
    validateByTika(file);        // 推荐:更准确安全

    // 保存逻辑略...
    return ResponseEntity.ok("上传成功");
}

三、可配置化(支持配置文件控制允许类型)

application.yml

yaml 复制代码
file:
  allowed-types:
    - image/png
    - image/jpeg
    - application/pdf

配置类注入:

java 复制代码
@ConfigurationProperties(prefix = "file")
@Data
public class FileConfig {
    private List<String> allowedTypes;
}

再注入 FileConfig 来校验:

java 复制代码
@Autowired
private FileConfig fileConfig;

if (!fileConfig.getAllowedTypes().contains(contentType)) {
    throw new IllegalArgumentException("不支持的文件类型");
}

四、其他建议

场景 建议
前端限制文件选择 <input accept="image/*">
后端强校验必不可少 防止绕过前端
存储前统一重命名处理 防止恶意脚本如 xx.jpg.exe
加白名单优于黑名单 拒绝所有不认识的类型