SpringMvc文件上传与下载
一、文件上传
前端传参的容器:
Formdata(表单数据)——放post请求的参数 ,字符流
QueryString —— 字符流,放get请求的参数 ,也就是 url?后面缀的参数
body——放的都是二进制流 , 上传文件一定使用post请求,
get请求不能带body数据和Formdata数据,post请求可以带QueryString和body数据和Formdata数据。
1、接收文件
需要导入的包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
在spring-mvc配置文件中配置
<!-- 配置文件上传-->
<bean id="MultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- defaultEncoding 默认的编码格式
maxInMemorySize在内存的最大值,影响的是接收文件的上传速度和完整性
maxUploadSize上传文件的总大小
maxUploadSizePerFile 用于上传多文件,设置每个上传文件的大小-->
<property name="defaultEncoding" value="utf8"></property>
</bean>
html页面
<form method="post" enctype="multipart/form-data" action="/upload/file.do">
<input type="file" name="myfile"><br>
<input type="file" name="myfile"><br>
<input type="submit" value="提交">
</form>
Controller类
注:MultipartFile myfile , MultipartFile的对象名字必须和前端html页面保持一致
单文件上传
@RequestMapping("/file.do")
public String upload(MultipartFile myfile) throws IOException {
System.out.println(myfile.getOriginalFilename());//获得原始文件名
File file = new File("/home/renzhipeng/" + myfile.getOriginalFilename());
myfile.transferTo(file);//transferTo 把file放到某个文件下面去
return "成功";
}
//多文件上传
@RequestMapping("/file.do")
public String upload(MultipartFile[] myfile) throws IOException {
for (MultipartFile multipartFile : myfile) {
File file = new File("/home/renzhipeng/" + multipartFile.getOriginalFilename());
multipartFile.transferTo(file);
}
return "成功";
}
2、保存文件
在web.xml中配置过滤器filter,用来改变编码格式
<!-- 过滤器filter,用来改变编码格式--->
<filter>
<filter-name>charSetfilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>charSetfilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
分布式的文件的保存过程:有很多服务器,它们共用一个数据库集群,数据集群连接到一个存储阵列,存储阵列用来保存文件,当接收到了文件以后,然后把文件放到存储阵列里,存储阵列将这个地址存到数据库集群里,然后返回一个info返回给用户,当另一台电脑访问这个文件,先去数据库里拿到这个地址,然后根据这个地址去存储阵列里拿到这个文件。
过滤器
filter属于servlet体系,在servlet前执行
spring CharacterEncodingFilter —— Spring框架提供的过滤器
过滤器与拦截器区别:
过滤器只负责请求,
拦截器负责请求和返回。
3、文件下载
简写一个controller类
//下载文件
@RequestMapping("/getImage.do")
public void queryFile(String path, HttpServletResponse response) throws IOException {
FileInputStream fis = new FileInputStream(WebConfig.FILE_PATH + path);
byte[] b = new byte[fis.available()];
fis.read(b);
response.setContentType("");
response.addHeader("Content-Disposition", "attachment;filename=down"+path);
response.getOutputStream().write(b);
}
二、拦截器(interceptor)
拦截器属于springmvc体系的,是在Controller之前执行的,可以设置很多个。
拦截器执行的顺序和在spring配置文件配置顺序一致。
在spring-mvc.xml中配置
<!-- 拦截器-->
<mvc:interceptors>
<!-- 将拦截器配置在mvc:interceptor里它就只关心这里面映射的链接-->
<!-- 配置在mvc:interceptor外,它关心所有的映射的链接-->
<!-- 拦截器执行的顺序和在spring配置文件配置顺序一致。-->
<mvc:interceptor>
<mvc:mapping path="/upload/file.do"/>
<ref bean="myInterceptor"></ref>
</mvc:interceptor>
<!-- <bean id="mySecondInterceptor" class="com.lanou.zhibo.controller.MySecondInterceptor"></bean>-->
<mvc:interceptor>
<mvc:mapping path="/user/**"/>
<ref bean="myInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>
<!-- 配置关联一个拦截器的bean-->
<bean id="myInterceptor" class="zhibo.controller.MyInterceptor"></bean>
写一个实现类实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter类
-
实现HandlerInterceptor接口不重写里面的方法有可能因为版本问题报错,所以需重写方法,相关业务才能执行。
-
继承HandlerInterceptorAdapter类 可以选择重写哪个方法
三个方法
-
preHandle 做一个前置的判断过程,判断这个请求能不能执行,通过反射来做一些事情,
-
postHandle 可以在这修改modeAndview,如果不想往回返modeAndview,就使用response直接返回
-
afterCompletion 在最终执行完成之后执行它
第一个拦截器:实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
//不重写里面的方法有可能因为版本问题报错,所以需重写方法,相关业务才能执行
/*
* preHandle 做一个前置的判断过程,判断这个请求能不能执行,通过反射来做一些事情,
* 参数:分开用 用前两个一般来判断参数的合法性,用第三个参数一般来判断用户状态合法性的
*
* postHandle 可以在这修改modeAndview,如果不想往回返modeAndview,就使用response直接返回
*
* afterCompletion 在最终执行完成之后执行它
* */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// handler 是一个HandlerMethod,spring告诉我们请求要执行的方法
HandlerMethod method = (HandlerMethod) handler;//HandlerMethod就是当前执行目标的方法
method.getMethod().getName();//拿到当前执行方法的名字
method.getMethod().invoke(method.getBean(),method.getMethodParameters());//执行这个方法
method.getBean().getClass().getName();//当前方法所属对象的名字
// getMethodAnnotation();//当前方法上加的注解
System.out.println("前置开始");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// modelAndView.getModel().put()
System.out.println("处理完成");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("全部结束");
}
}
第二个拦截器,继承HandlerInterceptorAdapter
public class MySecondInterceptor extends HandlerInterceptorAdapter {
// HandlerInterceptorAdapter 是一个类
// 可以选择重写哪个方法
public MySecondInterceptor() {
super();
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("second 前置");
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("second 后之处理");
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("second 结束处理");
super.afterCompletion(request, response, handler, ex);
}
//拦截并发处理
@Override
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("second concurrent 处理");
super.afterConcurrentHandlingStarted(request, response, handler);
}
}