在SpringBoot中,如何为MultipartFile参数创建自定义验证器?

gr8qqesn  于 2022-12-23  发布在  Spring
关注(0)|答案(2)|浏览(288)

bounty将在3天后过期。回答此问题可获得+300的声誉奖励。Dave正在寻找来自声誉良好来源的答案

我使用的是Sping Boot 2.4,我有以下控制器,其中的方法接受MultipartFile对象。

@RestController
public class MyController extends AbstractController

    ...
  @Override
  public ResponseEntity<ResponseData> add(
    ...
      @Parameter(description = "file detail") @Validated @RequestPart("myFile")
          MultipartFile myFile,
    ...
    ) {

我想验证这个MultipartFile包含我想要的数据(例如,是一个特定的mime类型)。所以我写了下面的验证器...

@Documented
@Constraint(validatedBy = MultipartFileValidator.class)
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MultipartFileConstraint {
  String message() default "Incorrect file type.";

  Class<?>[] groups() default {};

  Class<? extends Payload>[] payload() default {};
}

及其实现类...

public class MultipartFileValidator
    implements ConstraintValidator<MultipartFileConstraint, MultipartFile> {

  @Override
  public void initialize(final MultipartFileConstraint constraintAnnotation) {
    log.info("\n\n\n\nconstructor called\n\n\n\n");
  }

  @Override
  public boolean isValid(
      MultipartFile file, ConstraintValidatorContext constraintValidatorContext) {
    log.info("Validating file");
    ...
  }
}

然而,当我调用端点时,我没有看到验证器被调用(例如,日志语句不会被打印,断点也不会被命中)。我还需要做什么来为这个MultipartFile参数注册验证器?

kq4fsx7k

kq4fsx7k1#

根据Spring Documentation
也可以用于方法级别验证,指示特定类应该在方法级别验证(充当相应验证拦截器的切入点),但也可以选择指定带注解类中方法级别验证的验证组。

在方法级别应用这个注解允许覆盖特定方法的验证组,但不作为切入点;类级注解仍然是触发以开始的特定bean的方法验证所必需的。也可以用作自定义构造型注解或自定义组特定验证注解上的元注解。

所以,在这里我们必须记住什么是@Validated和验证器注解的位置.代码:
控制器类:@Validated在类级别添加,@ValidFile(自定义验证器注解)在方法中添加

@RestController
@Validated
@Slf4j
public  class MyController {

    @RequestMapping("/add")
    public ResponseEntity<ResponseData> add(@ValidFile @RequestParam("file")  MultipartFile file) {

        log.info("File Validated");
        return  ResponseEntity.status(HttpStatus.OK).body(new ResponseData("Valid file received"));
    }
}

验证器注解

@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {FileValidator.class})
public @interface ValidFile {
    Class<? extends Payload> [] payload() default{};
    Class<?>[] groups() default {};
    String message() default "Only pdf,xml,jpeg,jpg files are allowed";
}

验证器类

@Slf4j
public class FileValidator implements ConstraintValidator<ValidFile, MultipartFile> {

    @Override
    public void initialize(ValidFile validFile) {
        log.info("File validator initialized!!");
    }

    @Override
    public boolean isValid(MultipartFile multipartFile,
                           ConstraintValidatorContext   constraintValidatorContext) {
        log.info("Validating file");
        String contentType = multipartFile.getContentType();
        assert contentType != null;
        return isSupportedContentType(contentType);
    }
    private boolean isSupportedContentType(String contentType) {
        return contentType.equals("application/pdf")
                || contentType.equals("text/xml")
                || contentType.equals("image/jpg")
                || contentType.equals("image/jpeg");
    }
}

输出:成功:

{
    "message": "Valid file received"
}

异常处理程序

@ExceptionHandler(ConstraintViolationException.class)
 @ResponseStatus(HttpStatus.BAD_REQUEST)
 ResponseEntity<String> handleConstraintViolationException(ConstraintViolationException e) {
        return new ResponseEntity<>("Validation error: " + e.getMessage(), HttpStatus.BAD_REQUEST);
 }

失败:

Validation error: Only pdf,xml,jpeg,jpg files are allowed
uujelgoq

uujelgoq2#

下面是一个小例子,希望对大家有所帮助。

@Component
public class MultipartFileValidator implements Validator {
  @Override
  public boolean supports(Class < ? > clazz) {
    return MultipartFile.class.isAssignableFrom(clazz);
  }

  @Override
  public void validate(Object target, Errors errors) {
    MultipartFile multipartFile = (MultipartFile) target;
    if (multipartFile.isEmpty()) {
      // Add an error message to the errors list
      errors.rejectValue("file", "required.file");
    }
  }
}

相关问题