首页 > 其他分享 >@FileLimit – AOP最佳实践:上传文件大小限制

@FileLimit – AOP最佳实践:上传文件大小限制

时间:2022-12-03 16:36:26浏览次数:43  
标签:文件大小 MB max AOP import annotation FileLimit

@FileLimit 结构分析

 

 

 1、FileLimitUnit 定义枚举:文件的单位

public enum FileLimitUnit {
    KB, MB, GB
}

2、定义注解

import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**
 * @Author :zanglk
 * @DateTime :2022/1/25 09:49
 * @Description :FileLimit 注解,内置参数value,max,以及文件单位
 * @Notes :To change this template:Click IDEA-Preferences to search 'File Templates'
 */
@Documented
@Target(ElementType.METHOD) // 作用与方法上
@Retention(RetentionPolicy.RUNTIME) // RUNTIME: 在运行时有效(即运行时保留)
public @interface FileLimit {
    @AliasFor("max") // @AliasFor 表示其可与max互换别名:当注解指定value时,为max赋值
    int value() default 5;
    // 定义单个文件最大限制
    @AliasFor("value") // @AliasFor 表示其可与value互换别名:当注解指定max是,为value赋值
    int max() default 5;
    // 文件单位,默认定义为MB
    FileLimitUnit unit() default FileLimitUnit.MB;
}

3、注解使用

任意方法添加,如果不传入value,就使用注解默认值5。
    @FileLimit(value = 25,unit = FileLimitUnit.MB)
    @FileLimit(unit = FileLimitUnit.MB)
    @FileLimit

4、AOP拦截控制

注意 AOP拦截我在输出异常信息时,转换了文件大小,所以我使用我自己的工具类,这里我就不贴代码了。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@Aspect
@Component
public class FileLimitAop {
    // 定义默认的单个文件最大限制 5MB 。5Mb = 5 * 1024 * 1024 byte
    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;
    // 注意,这里要指定注解的全限定类名。不然无法进入AOP拦截自定义注解FileLimit
    @Pointcut("@annotation(com.zanglikun.springdataredisdemo.aop.fileLimitAop.FileLimit)")
    public void pointcut() {
    }
    /**
     * 方法体执行之前执行
     */
    @Before("pointcut()")
    public void beforeLog(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        FileLimit annotation = AnnotationUtils.getAnnotation(signature.getMethod(), FileLimit.class);
        if (null == annotation) {
            return;
        }
        // 执行文件检查
        fileSizeLimit(joinPoint, annotation);
    }
    // 判定文件大小是否合格,如果不合格,直接跑出自定义异常FileLimitException。进而阻塞方法正常进行。
    private void fileSizeLimit(JoinPoint joinPoint, FileLimit annotation) {
        // 获取AOP签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取注解的指定最大文件大小
        long maxFileSize = getAnnotationMaxFileSize(annotation);
        // 通过AOP签名 获取接口参数,调用方法获取文件
        MultipartFile multipartFile = getMultipartFile(signature.getParameterNames(), signature.getParameterTypes(), joinPoint.getArgs());
        if (null != multipartFile) {
            if (0 == multipartFile.getSize()) {
                throw new FileLimitException("文件数据(大小为0)异常.");
            }
            if (multipartFile.getSize() > maxFileSize) {
                String msg = "文件大小不得超过 " + annotation.max() + annotation.unit().toString();
                throw new FileLimitException(msg+" ,当前文件大小是 "+FileSizeOut.printFileSize(multipartFile.getSize()));
            }
        }
    }
    // 获取使用注解指定最大文件大小。如果没有指定文件大小,就用默认值
    public long getAnnotationMaxFileSize(FileLimit fileLimit) {
        if (null == fileLimit) {
            return MAX_FILE_SIZE;
        }
        switch (fileLimit.unit()) {
            case MB:
                return (long) fileLimit.max() * 1024 * 1024;
            case KB:
                return (long) fileLimit.max() * 1024;
            default:
                return MAX_FILE_SIZE;
        }
    }
    // 使用AOP获取目标请求方法携带的参数。我们当前只需要解析File
    private MultipartFile getMultipartFile(String[] paramNames, Class[] paramTypes, Object[] paramObjs) {
        for (int i = 0; i < paramNames.length; i++) {
            if (paramTypes[i] != MultipartFile.class) {
                continue;
            }
            return (MultipartFile) paramObjs[i];
        }
        return null;
    }
}

测试

测试前,请添加或修改配置文件,避免因为Servlet大小限制了。

# 限制Tomcat Servlet单文件大小、以及总请求大小,-1则不限制!
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
@RestController
@RequestMapping("/testFileLimit")
public class TestFileLimit {
    @RequestMapping("/upload")
    //@FileLimit(value = 25,unit = FileLimitUnit.MB)
    //@FileLimit(unit = FileLimitUnit.MB)
    @FileLimit
    public void upLoad(MultipartFile file) {
        System.out.println("请求进入喽");
    }
}

我上传一个视频文件461.0MB

2022-10-25 12:55:56.245 ERROR 42691 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.zanglikun.springdataredisdemo.aop.FileLimitException: 文件大小不得超过 5MB ,当前文件大小是 461.0MB] with root cause
com.zanglikun.springdataredisdemo.aop.FileLimitException: 文件大小不得超过 5MB ,当前文件大小是 461.0MB

拦截成功!完结

标签:文件大小,MB,max,AOP,import,annotation,FileLimit
From: https://www.cnblogs.com/kaixin001/p/16948252.html

相关文章

  • springIOC和AOP
    IOC(InverseofControl:控制反转)是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。Ioc在其他语言中也有应用,并非spring特有。Ioc容器是Spring用......
  • How to get file size in Python? 获取文件大小Python
    HowtogetfilesizeinPython?WecanfollowdifferentapproachestogetthefilesizeinPython.It’simportanttogetthefilesizeinPythontomonitorfi......
  • 7.2 图像文件压缩。使用PIL库对图像进行等比例压缩,无论压缩前文件大小如何,压缩后文件
    python实现图像文件等比例压缩 使用Image类中的open()方法从文件加载图像,使用其中的size属性获得图像的宽度和高度。os模块中的path.getsize()方法可以获得文件的大小,......
  • .Net Core 5.0 通过Swagger Api上传文件大小被限制,报error: request entity too large
    1、在Startup中添加以下代码publicvoidConfigureServices(IServiceCollectionservices){services.Configure<FormOptions>(options=>{//Setth......
  • Spring中的AOP——在Advice方法中获取目标方法的参数
    Object[]getArgs:返回目标方法的参数SignaturegetSignature:返回目标方法的签名ObjectgetTarget:返回被织入增强处理的目标对象ObjectgetThis:返回AOP框架为目标......
  • aop切点定义表达式详解
    目录1.execution2.within3.this4.target5.args6.bean7.@args8.@target9.@within10.@annotation11.组合表达式1.execution可以匹配到方法级别格式如下:execution(方法访......
  • Spring的AOP简介和Spring中的通知使用方法以及异常
    AOP中关键性概念连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.目标(Target):被通知(被代理)的对象注1:完成具体的业务逻辑通知(Advice):在某个特定的......
  • aop注解
    注解aop开发步骤1 使用@Aspect标注切面类2 使用@通知注解标注通知方法@Component("myAspect")@Aspect//标注当前MyAspect是一个切面类publicclassMyAs......
  • aop切点表达式写法
    表达式语法excution([修饰符]返回值类型包名.类名.方法名(参数))* 访问修饰符可以省略* 返回值类型、包名、类名、方法名、可以使用星号*代......
  • AOP相关概念
    常用术语Target(目标对象):代理的目标对象Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类JoinPoint(连接点):所谓连接点是指那些被拦截到的点。在spr......