SpringBoot?上傳文件判空以及格式檢驗(yàn)流程
基于jsr303 通過(guò)自定義注解實(shí)現(xiàn),實(shí)現(xiàn)思路:
存在一些瑕疵,后續(xù)補(bǔ)充完善。
加入依賴(lài)
部分版本已不默認(rèn)自動(dòng)引入該依賴(lài),選擇手動(dòng)引入
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
創(chuàng)建自定義注解以及實(shí)現(xiàn)類(lèi)
目錄結(jié)構(gòu):
FileNotEmpty
自定義注解FileNotEmptyValidator
單文件校驗(yàn)FilesNotEmptyValidator
多文件校驗(yàn)
/** * jsr303 文件格式校驗(yàn)注解 * * @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 "文件格式不正確"; /** * 校驗(yàn)組 * * @return the class [ ] */ Class<?>[] groups() default {}; /** * Payload class [ ]. * * @return the class [ ] */ Class<? extends Payload>[] payload() default {}; /** * 需要校驗(yàn)的格式數(shù)組 * * @return the string [ ] */ String[] format() default {}; /** * 是否必填 為false時(shí)文件為空則不校驗(yàn)格式,不為空則校驗(yàn)格式 * 為true時(shí)文件不能為空且需要驗(yàn)證格式 * * @return the boolean */ boolean required() default true;
/** * 單文件校驗(yàn) * * @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; } }
/** * 多文件校驗(yàn) * * @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; } }
全局異常處理
/** * 統(tǒng)一異常處理 * * @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("未知錯(cuò)誤:").append("請(qǐng)聯(lián)系后臺(tái)運(yùn)維人員檢查處理!"); } 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 項(xiàng)目編號(hào) * @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; } }
結(jié)果展示
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Spring Data JPA系列之投影(Projection)的用法
本篇文章主要介紹了詳解Spring Data JPA系列之投影(Projection)的用法,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07java接口私有方法實(shí)現(xiàn)過(guò)程解析
這篇文章主要介紹了java接口私有方法實(shí)現(xiàn)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java之判斷2000~2023年有哪些年份是閏年并打印輸出
這篇文章主要介紹了Java之判斷2000~2023年有哪些年份是閏年并打印輸出,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12SpringBoot實(shí)現(xiàn)異步事件驅(qū)動(dòng)的方法
本文主要介紹了SpringBoot實(shí)現(xiàn)異步事件驅(qū)動(dòng)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06java 對(duì)文件夾目錄進(jìn)行深度遍歷實(shí)例代碼
這篇文章主要介紹了java 對(duì)文件夾目錄進(jìn)行深度遍歷實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03Spring?Boot?使用?Hutool-jwt?實(shí)現(xiàn)?token?驗(yàn)證功能
JWT?就是一種網(wǎng)絡(luò)身份認(rèn)證和信息交換格式,這篇文章主要介紹了Spring Boot使用Hutool-jwt實(shí)現(xiàn)token驗(yàn)證,需要的朋友可以參考下2023-07-07淺談mybatis中SQL語(yǔ)句給boolean類(lèi)型賦值問(wèn)題
這篇文章主要介紹了淺談mybatis中SQL語(yǔ)句給boolean類(lèi)型賦值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11