SpringBoot 上传文件判空以及格式检验

基于jsr303 通过自定义注解实现,实现思路:
在这里插入图片描述
存在一些瑕疵,后续补充完善。

加入依赖

部分版本已不默认自动引入该依赖,选择手动引入

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

创建自定义注解以及实现类

目录结构:

  • FileNotEmpty 自定义注解
  • FileNotEmptyValidator 单文件校验
  • FilesNotEmptyValidator 多文件校验
/**
 * jsr303 文件格式校验注解
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -11-29 10:16:03
 */
@Documented
@Constraint(
        validatedBy = {FileNotEmptyValidator.class, FilesNotEmptyValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FileNotEmpty {
    /**
     * Message string.
     *
     * @return the string
     */
    String message() default "文件格式不正确";

    /**
     * 校验组
     *
     * @return the class [ ]
     */
    Class<?>[] groups() default {};

    /**
     * Payload class [ ].
     *
     * @return the class [ ]
     */
    Class<? extends Payload>[] payload() default {};

    /**
     * 需要校验的格式数组
     *
     * @return the string [ ]
     */
    String[] format() default {};

    /**
     * 是否必填 为false时文件为空则不校验格式,不为空则校验格式
     * 为true时文件不能为空且需要验证格式
     *
     * @return the boolean
     */
    boolean required() default true;
/**
 * 单文件校验
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -11-29 10:16:03
 */
public class FileNotEmptyValidator implements ConstraintValidator<FileNotEmpty, MultipartFile> {

    private Set<String> formatSet = new HashSet<>();
    private boolean required;


    @Override
    public void initialize(FileNotEmpty constraintAnnotation) {
        String[] format = constraintAnnotation.format();
        this.formatSet = new HashSet<>(Arrays.asList(format));
        this.required = constraintAnnotation.required();
    }

    @Override
    public boolean isValid(MultipartFile multipartFile, ConstraintValidatorContext constraintValidatorContext) {

        if (multipartFile == null || multipartFile.isEmpty()) {
            return !required;
        }

        String originalFilename = multipartFile.getOriginalFilename();
        assert originalFilename != null;
        String type = originalFilename.substring(originalFilename.lastIndexOf('.') + 1).toLowerCase();
        if (!formatSet.isEmpty()) {
            return formatSet.contains(type);
        }


        return true;
    }
}
/**
 *  多文件校验
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -11-29 10:16:03
 */
public class FilesNotEmptyValidator implements ConstraintValidator<FileNotEmpty, MultipartFile[]> {

    private Set<String> formatSet = new HashSet<>();
    private boolean required;

    @Override
    public void initialize(FileNotEmpty constraintAnnotation) {
        String[] format = constraintAnnotation.format();
        this.formatSet = new HashSet<>(Arrays.asList(format));
        this.required = constraintAnnotation.required();
    }

    @Override
    public boolean isValid(MultipartFile[] multipartFiles, ConstraintValidatorContext constraintValidatorContext) {
        if (multipartFiles == null || multipartFiles.length == 0) {
            return !required;
        }

        for (MultipartFile file : multipartFiles) {
            String originalFilename = file.getOriginalFilename();
            assert originalFilename != null;
            String type = originalFilename.substring(originalFilename.lastIndexOf('.') + 1).toLowerCase();
            if (formatSet.isEmpty() || !formatSet.contains(type)) {
                return false;
            }
        }


        return true;
    }
}

全局异常处理

/**
 * 统一异常处理
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -11-29 10:16:03
 */
@ControllerAdvice
public class ExceptionHandle {
    private final static Logger logger = LoggerFactory.getLogger(ExceptionHandle.class);
       
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result<String> handle(Exception e) {
        logger.error(e.getMessage());
        StringBuilder stringBuilder = new StringBuilder();             
            //jsr303异常
          if (e instanceof ConstraintViolationException) {
            ConstraintViolationException ex = (ConstraintViolationException)e;
            Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
            for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                stringBuilder.append(constraintViolation.getMessageTemplate());
            }
        } else if (e instanceof BindException) {
            BindException bindException = (BindException)e;
            stringBuilder.append(bindException.getFieldErrors()
                .stream()
                .map(FieldError::getDefaultMessage)
                .collect(Collectors.joining(",")));
        } else {
            stringBuilder.append("未知错误:").append("请联系后台运维人员检查处理!");           
        }
        return  ResultUtil.fail(stringBuilder.toString());
    }
    
}

使用示例

/**
 * 文件上传示例接口
 *
 * @author maofs
 * @version 1.0
 * @date 2021 -11-19 16:08:26
 */
@RestController
@Validated
@RequestMapping("/annex")
public class AnnexController {
 @Resource
 private IAnnexService annexService;

   /**
     * 文件上传示例1
     *
     * @param uploadDTO the upload dto
     * @return the result
     */
    @PostMapping(value = "/upload1")
    public Result<String> upload(@Valid AnnexUploadDTO uploadDTO) {

        return Boolean.TRUE.equals(annexService.upload(uploadDTO)) ? ResultUtil.success() : ResultUtil.fail();
        
    }
    
   /**
     * 文件上传示例2
     *
     * @param number      项目编号
     * @param pictureFile 图片文件
     * @param annexFile   附件文件
     * @return result result
     */
    @PostMapping(value = "/upload2")
    public Result<String> upload(@NotBlank(@FileNotEmpty(format = {"png", "jpg"}, message = "图片为png/jpg格式", required = false)
                                         MultipartFile pictureFile, @FileNotEmpty(format = {"doc", "docx", "xls", "xlsx"}, message = "附件为doc/docx/xls/xlsx格式", required = false)
                                         MultipartFile annexFile) {       
        return Boolean.TRUE.equals(annexService.upload( pictureFile, annexFile)) ? ResultUtil.success() : ResultUtil.fail();
    }
    
	@Data
	static class AnnexUploadDTO{ 
	    @FileNotEmpty(format = {"pdf","doc","zip"}, message = "文件为pdf/doc/zip格式")
	    private MultipartFile[] file;
    }
}

结果展示

接口1效果展示
接口2效果展示

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值