SpringBoot 上传文件判空以及格式检验流程
作者:?吾?非?水 发布时间:2023-01-19 05:07:36
标签:上传文件,判空,格式检验
基于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;
}
}
结果展示
来源:https://blog.csdn.net/weixin_43931248/article/details/122000087
0
投稿
猜你喜欢
- 本文实例讲述了Java定义泛型方法。分享给大家供大家参考,具体如下:一 点睛1 如果定义类、接口是没有使用类型形参,但定义方法时想自己定义类
- HashMap和HashTable,这二者的区别经常被别人问起,今天在此总结一下。(一)继承的历史不同public class
- 我们知道java程序是运行在JVM中的,而JVM就是构建在内存上的虚拟机,那么内存模型JMM是做什么用的呢?我们考虑一个简单的赋值问题:in
- 前段时间写了一篇基于mybatis实现的多数据源博客。感觉不是很好,这次打算加入git,来搭建一个基于Mybatis-Plus的多数据源项目
- Android Build类的详解及简单实例一、类结构:java.lang.Object? android.os.Build二、类概述:从系
- 知乎是一个真实的网络问答社区,社区氛围友好、理性、认真,连接各行各业的精英。他们分享着彼此的专业知识、经验和见解,为中文互联网源源不断地提供
- 最近有个项目的几张表,数量级在千万以上,技术栈是SpringBoot+Mybatis-plus+MySQL。如果使用单表,在进行查询操作,非
- springboot启动是通过一个main方法启动的,代码如下@SpringBootApplicationpublic class Appl
- 类与对象:类是抽象的数据类型,对象是抽象的数据类型的具体化。使用new 关键字创建对象,默认初始化为null一个项目只存在一个main方法,
- 场景网站智能问答场景,需要对多个分类查询,结果聚合展示由于每种分类都有自己的业务逻辑,有的需要查询数据库中间库,有的需要查询elastics
- 推荐教程IntelliJ IDEA 2020最新激活码(亲测有效,可激活至 2089 年)最新idea2021注册码永久激活(激活到2100
- 这篇文章主要介绍了java实现上传文件类型检测过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 一、什么是冒泡排序冒泡排序的英文是bubble sort,它是一种基础的交换排序。说到冒泡是不是就想起了快乐肥宅水呢?汽水中有许多小小的水泡
- 一:什么是classpath?classpath指的就是 *.java文件,资源文件等编译后存放的位置,对于maven项目就是指 targe
- package com.chase.test;import java.util.ArrayList;import java.util.Has
- 打开首页,明显看到链接是https打头,https和http的通信协议差别,在于https安全性更高:http和https的差别很明显,二者
- @ConditionalOnProperty作用及用法在spring boot中有时候需要控制配置类是否生效,可以使用@Conditiona
- 最近在配置OpenCV的时候,由于使用的是VS2019,结果找不到Microsoft.Cpp.X64.user这个文件。导致每次新建项目都得
- MyBatis-Plus不使用数据库默认值的问题有时候我们在设计数据表时希望某些字段使用默认值,比如create_time、和update_
- mysql插件实现原理官网的关键信息参考文档https://mybatis.org/mybatis-3/zh/configuration.h