全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-18 6 分钟 ✍️ juanwangdev

Spring MVC 文件大小与类型限制

文件上传时需要限制文件大小和类型,防止服务器资源滥用和安全隐患。

配置文件大小限制

application.yml配置

YAML
spring:
  servlet:
    multipart:
      max-file-size: 10MB        # 单个文件最大10MB
      max-request-size: 100MB    # 总请求最大100MB
      file-size-threshold: 2KB   # 超过2KB写入临时文件
      location: /tmp/upload      # 临时文件存储位置

application.properties配置

properties
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
spring.servlet.multipart.file-size-threshold=2KB
spring.servlet.multipart.location=/tmp/upload

配置类方式

Java
@Configuration
public class MultipartConfig {

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        factory.setMaxFileSize(DataSize.ofMegabytes(10));
        factory.setMaxRequestSize(DataSize.ofMegabytes(100));
        factory.setFileSizeThreshold(DataSize.ofKilobytes(2));
        factory.setLocation("/tmp/upload");
        return factory.createMultipartConfig();
    }
}

文件大小限制异常处理

Java
@RestControllerAdvice
public class FileUploadExceptionHandler {

    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public ResponseEntity<Map<String, Object>> handleMaxSizeException(
            MaxUploadSizeExceededException e) {

        Map<String, Object> response = new HashMap<>();
        response.put("code", 400);
        response.put("message", "文件大小超过限制");

        long maxFileSize = e.getMaxFileSize();
        response.put("maxSize", maxFileSize / 1024 / 1024 + "MB");

        return ResponseEntity.badRequest().body(response);
    }
}

文件类型限制

Controller手动校验

Java
@RestController
@RequestMapping("/api/upload")
public class UploadController {

    private static final Set<String> ALLOWED_TYPES = Set.of(
        "jpg", "jpeg", "png", "gif", "pdf", "doc", "docx"
    );

    private static final Map<String, List<String>> TYPE_EXTENSIONS = Map.of(
        "image", List.of("jpg", "jpeg", "png", "gif"),
        "document", List.of("pdf", "doc", "docx", "xls", "xlsx"),
        "video", List.of("mp4", "avi", "mov")
    );

    @PostMapping("/restricted")
    public String uploadRestricted(@RequestParam("file") MultipartFile file) {
        validateFile(file);
        return saveFile(file);
    }

    private void validateFile(MultipartFile file) {
        if (file.isEmpty()) {
            throw new ValidationException("文件为空");
        }

        // 校验文件大小
        if (file.getSize() > 10 * 1024 * 1024) {
            throw new ValidationException("文件大小不能超过10MB");
        }

        // 校验文件扩展名
        String extension = getExtension(file.getOriginalFilename());
        if (!ALLOWED_TYPES.contains(extension.toLowerCase())) {
            throw new ValidationException("不允许的文件类型: " + extension);
        }

        // 校验ContentType
        String contentType = file.getContentType();
        if (!isValidContentType(contentType)) {
            throw new ValidationException("不允许的ContentType: " + contentType);
        }
    }

    private String getExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    private boolean isValidContentType(String contentType) {
        if (contentType == null) {
            return false;
        }

        return contentType.startsWith("image/") ||
               contentType.equals("application/pdf") ||
               contentType.startsWith("application/msword") ||
               contentType.startsWith("application/vnd.");
    }
}

自定义校验注解

Java
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FileSizeValidator.class)
public @interface MaxFileSize {
    String message() default "文件大小超过限制";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    long maxSize() default 10 * 1024 * 1024;    // 默认10MB
}

public class FileSizeValidator implements ConstraintValidator<MaxFileSize, MultipartFile> {

    private long maxSize;

    @Override
    public void initialize(MaxFileSize constraintAnnotation) {
        this.maxSize = constraintAnnotation.maxSize();
    }

    @Override
    public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
        if (file == null || file.isEmpty()) {
            return true;
        }
        return file.getSize() <= maxSize;
    }
}

文件类型校验注解

Java
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FileTypeValidator.class)
public @interface AllowedFileTypes {
    String message() default "不允许的文件类型";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};

    String[] types() default {};
}

public class FileTypeValidator implements ConstraintValidator<AllowedFileTypes, MultipartFile> {

    private Set<String> allowedTypes;

    @Override
    public void initialize(AllowedFileTypes constraintAnnotation) {
        this.allowedTypes = Set.of(constraintAnnotation.types());
    }

    @Override
    public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
        if (file == null || file.isEmpty()) {
            return true;
        }

        String extension = getExtension(file.getOriginalFilename());
        return allowedTypes.contains(extension.toLowerCase());
    }

    private String getExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }
}

使用校验注解

Java
@PostMapping("/validated")
public String uploadValidated(
        @MaxFileSize(maxSize = 5 * 1024 * 1024, message = "文件不能超过5MB")
        @AllowedFileTypes(types = {"jpg", "png", "gif"}, message = "只允许图片文件")
        @RequestParam("file") MultipartFile file) {

    return saveFile(file);
}

文件内容校验

Java
private void validateFileContent(MultipartFile file) {
    try {
        InputStream inputStream = file.getInputStream();

        // 校验图片文件
        if (isImageFile(file)) {
            BufferedImage image = ImageIO.read(inputStream);
            if (image == null) {
                throw new ValidationException("图片内容无效");
            }
        }

        // 校验PDF文件
        if (isPdfFile(file)) {
            PDFParser parser = new PDFParser(inputStream);
            parser.parse();
            // ...PDF内容校验
        }

    } catch (IOException e) {
        throw new ValidationException("文件内容校验失败");
    }
}

private boolean isImageFile(MultipartFile file) {
    String contentType = file.getContentType();
    return contentType != null && contentType.startsWith("image/");
}

文件类型白名单

Java
@Component
public class FileTypeWhitelist {

    private final Map<String, FileTypeConfig> configs;

    public FileTypeWhitelist() {
        configs = Map.of(
            "avatar", new FileTypeConfig(
                List.of("jpg", "jpeg", "png"),
                2 * 1024 * 1024,
                List.of("image/jpeg", "image/png")
            ),
            "document", new FileTypeConfig(
                List.of("pdf", "doc", "docx", "xls", "xlsx"),
                20 * 1024 * 1024,
                List.of("application/pdf", "application/msword")
            ),
            "video", new FileTypeConfig(
                List.of("mp4", "avi"),
                100 * 1024 * 1024,
                List.of("video/mp4", "video/avi")
            )
        );
    }

    public boolean isAllowed(String category, String extension) {
        FileTypeConfig config = configs.get(category);
        return config != null && config.extensions.contains(extension.toLowerCase());
    }

    public boolean isSizeAllowed(String category, long size) {
        FileTypeConfig config = configs.get(category);
        return config != null && size <= config.maxSize;
    }
}

@Data
@AllArgsConstructor
class FileTypeConfig {
    private List<String> extensions;
    private long maxSize;
    private List<String> contentTypes;
}

配置限制对比

配置项说明默认值
max-file-size单文件最大大小1MB
max-request-size请求总大小10MB
file-size-threshold内存阈值0
location临时文件目录系统临时目录

MIME类型参考

文件类型MIME类型
jpg/jpegimage/jpeg
pngimage/png
gifimage/gif
pdfapplication/pdf
docapplication/msword
docxapplication/vnd.openxmlformats-officedocument.wordprocessingml.document
xlsapplication/vnd.ms-excel
xlsxapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheet
mp4video/mp4
txttext/plain

要点总结

  • spring.servlet.multipart配置文件大小限制
  • MaxUploadSizeExceededException处理超限异常
  • 手动校验文件扩展名和ContentType
  • 自定义校验注解可声明式配置限制
  • 白名单机制统一管理文件类型限制
  • 内容校验确保文件真实类型匹配

📝 发现内容有误?点击此处直接编辑

← 上一篇 Spring MVC 文件下载实现
下一篇 → Spring MVC Hibernate Validator
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库