SpringBoot项目文件上传校验(注解版)

需求

要实现了一个文件上传和验证的功能,具有以下特点:

  1. 自定义注解:`FileValidation`注解用于标记需要进行文件验证的方法。

  2. 文件验证拦截器:`FileValidationInterceptor`拦截器会在每个请求处理之前被调用。如果请求处理的方法上有`FileValidation`注解,那么拦截器会获取请求中的文件,并进行验证。

  3. 文件验证:文件验证的逻辑在`FileValidationUtils`的`validateFile`方法中实现。这个方法会检查文件的MIME类型和文件扩展名是否匹配,以及文件的内容是否符合预期的文件格式。

  4. 支持单个和多个文件上传:在`Controller`中,`upload`方法接受一个`MultipartFile`参数,表示上传的文件。在`FileValidationInterceptor`中,拦截器会检查请求中是否有名为"file"的参数,如果有,就获取这个参数并进行验证。同时,拦截器也支持多个文件上传,它会检查请求中是否有名为"files"的参数,如果有,就获取这个参数(一个文件列表),并对列表中的每个文件进行验证。

  5. 错误处理:如果文件验证失败,`validateFile`方法会抛出一个异常。在`FileValidationInterceptor`中,如果捕获到这个异常,拦截器会停止请求的处理,并返回一个错误响应。

在Spring Boot中,拦截器和注解是常用的技术,用于实现各种复杂的功能。以下代码的设计和实现都遵循了Spring Boot的最佳实践。

创建自定义注解

java 复制代码
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FileValidation {
}

拦截器

java 复制代码
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    if (handler instanceof HandlerMethod) {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        FileValidation fileValidation = handlerMethod.getMethodAnnotation(FileValidation.class);
        if (fileValidation != null) {
            if (request instanceof MultipartHttpServletRequest) {
                MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
                MultipartFile file = multipartRequest.getFile("file");
                List<MultipartFile> files = multipartRequest.getFiles("files");
                if (file != null) {
                    if (file.isEmpty()) {
                        throw new RuntimeException("Invalid file");
                    }
                    validateFile(file);
                } else if (files != null && !files.isEmpty()) {
                    for (MultipartFile f : files) {
                        if (f.isEmpty()) {
                            throw new RuntimeException("Invalid file");
                        }
                        validateFile(f);
                    }
                } else {
                    throw new RuntimeException("No file or files attribute found in request");
                }
            }
        }
    }
    return true;
}

springboot注册拦截器

java 复制代码
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new FileValidationInterceptor());
    }
}

controller使用方法

java 复制代码
@PostMapping("/uploadSingle")
@FileValidation
public ResponseEntity<ResponseResult<ExportResponseVo>> uploadSingle(@Param("file") MultipartFile file) throws Exception{
    // ...
}

@PostMapping("/uploadMultiple")
@FileValidation
public ResponseEntity<ResponseResult<ExportResponseVo>> uploadMultiple(@Param("files") MultipartFile[] files) throws Exception{
    // ...
}
相关推荐
_codemonster3 分钟前
配置Tomcat时为啥要配置Artifacts
java·tomcat·firefox
无心水6 分钟前
2025,一路有你!
java·人工智能·分布式·后端·深度学习·架构·2025博客之星
m0_528749006 分钟前
C语言错误处理宏两个比较重要的
java·linux·算法
不想秃头的程序员11 分钟前
Vue3 子传父全解析:从基础用法到实战避坑
前端·vue.js·面试
weixin1997010801615 分钟前
海外淘宝商品详情页前端性能优化实战
大数据·前端·python
独自破碎E27 分钟前
BISHI43 讨厌鬼进货
android·java·开发语言
MX_935931 分钟前
Spring xml 方式整合第三方框架总结加案例
xml·java·spring
没有bug.的程序员35 分钟前
服务网格(Istio)与传统微服务深度对垒:流量治理内核、代码侵入性博弈与运维收益实战指南
java·运维·微服务·istio·流量治理内核·代码侵入性
小龙37 分钟前
【开源项目】航空订票系统(界面 + 数据库 + 运行手册)开源说明
前端·航空订票系统
该叫啥37 分钟前
Spring Bean 生命周期
java·spring·servlet