SpringBoot文件上传+拦截器
静态资源访问
- 使用IDEA创建Spring Boot项目,会默认创建出classpath:/static/目录,静态资源(网站图片,css,js)一般放在这个目录即可。【若前后端分离开发,该目录不存放内容】
- 如果默认的静态资源过滤策略不能满足开发需求,可以自定义静态资源过滤策略。
- 在application.properties中直接定义过滤规则和静态资源位置:
spring.mvc.static-path-pattern=/images/**
spring.resources.static-locations=classpath:/css
- 过滤规则为/static/**,静态资源位置为classpath:/static/
文件上传
- 表单的enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。
- 当表单的enctype=“application/x-www-form-urlencoded”(默认)时,form表单中的数据格式为:key=value&key=value
- 当表单的enctype=“multipart/form-data”时,其传输数据形式如下:
SpringBoot实现文件上传功能
SpringBoot工程嵌入的tomcat限制了请求的文件大小,每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb(单次可以请求多个文件)。
要更改这个默认值需要在配置文件(application.properties)中加入两个配置:
#单个文件大小
spring.servlet.multipart.max-file-size=10MB
#单次请求所有文件的大小总和
spring.servlet.multipart.max-request-size=10MB
当表单的enctype=“multipart/form-data”时,可以使用MultipartFile获取上传的文件数据,再通过TransferTo方法将其写到磁盘中(可以写入到服务器的某个目录中)。
@RestController
public class FileUploadController {
@PostMapping("/upload")
public String up(String nickname, MultipartFile photo, HttpServletRequest request) throws IOException{
System.out.println(nickname);
// 获取图片的原始名称
System.out.println(photo.getOriginalFilename());
// 获取文件类型
System.out.println(photo.getContentType());
// 获取服务器对应的路径,web服务器运行目录(动态变化,部署到其他服务器则路径改变,动态获取)
String path=request.getServletContext().getRealPath("/upload/");
System.out.println(path);
saveFile(photo,path);
return "上传成功";
}
public void saveFile(MultipartFile photo,String path) throws IOException{
// 判断存储的目录是否存在,如果不存在则创建
// 创建File对象,将路径传到该对象进行判断
File dir=new File(path);
if(!dir.exists()){
// 创建目录
dir.mkdir();
}
// 最终存储的文件
File file = new File(path+photo.getOriginalFilename());
photo.transferTo(file);
}
拦截器
拦截器在Web系统中很常见,对于某些全局统一的操作,可以提取到拦截器中实现(不同的控制器统一的操作,拦截器用于拦截请求,对统一操作做处理)。拦截器大致有以下几种使用场景:
- 权限检查:如登录检测,进入处理程序检测是否登录,如果没有,直接返回登录页面。
- 性能监控:有时系统在某段时间莫名其妙很慢,可以通过拦截器在进入处理程序之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。
- 通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有提取Locale、Theme信息等,只要是多个处理程序都需要的,即可使用拦截器实现。
SpringBoot中拦截器
SpringBoot定义了HandlerInterceptor接口来实现自定义拦截器的功能,该接口定义了preHandle(最常用)、postHandle、afterCompletion三种方法,通过重写这三种方法实现请求前、请求后等操作。
SpringBoot中拦截器工作示意图:
public class LoginInterceptor implements HandlerInterceptor {
// 在请求处理之前调用(Controller方法调用之前)
// preHandle方法默认return true
// request为前端发来的请求,response为后端给前端的响应
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception{
System.out.println("LoginInterceptor");
//添加判断
return true;
}
}
拦截器注册
- addPathPatterns方法定义拦截的地址
- excludePathPatterns定义排除某些地址不被拦截
- 添加的一个拦截器没有addPathPatterns任何一个url,则默认拦截所有请求
- 如果没有excludePathPatterns任何一个请求,则默认不放过任何一个请求
//加上@Configuration注解Springboot会自动读取这个类,以下的配置才能生效
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry){
// 如果不使用addPathPatterns添加路径,则拦截所有请求
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");
}
}