关于SpringMVC中文件的上传与下载
学习要点
文件的上传
文件的下载
SpringMVC拦截器
文件的上传
使用SpringMVC文件上传约束
必须使用一下方式才可以上传文件:
必须使用POST请求
必须设置enctype="multipart/form-data"
一旦设置了enctype="multipart/form-data",浏览器会采用二进制的方式来处理表单数据,对于文件的上传需要涉及服务器的原始状态响应解析,Apache2003年发布了开源项目commons FileUpload,其很快成为Servlet/jsp的文件上传首选。
但是这种方式需要在Servlet中完成,而SpringMVC则又在此开源项目上封装了更为简单的方式。
Springmvc为文件上传提供了更直接的方式,这种方式是即插即用的MultipartResolver实现的,SpringMVC使用Apache commons FileUpload技术实现了一个MultipartResolver实现类:CommonsMultipartResolver,因此,SpringMVC的文件上传还是需要依赖Apache的Common FileUpload组件。
文件上传代码示例:
1.配置文件的配置:(Spring默认是不装配MultipartResolver组件的,如果需要使用Spring的上传功能,需要进行配置)
<!--文件上传的配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--文件上传的默认编码方式,请求的编码格式必须和jsp的pageEncoding属性值一致,以便读取表单内容,默认iso-8859-1-->
<property name="defaultEncoding" value="UTF-8"></property>
<!--文件上传的大小限制 大小为10M 单位为b-->
<property name="maxUploadSize" value="10485760"/>
</bean>
2.jsp代码(需要配置页面属性为enctype=”multipart/form-data”)
<%--
Created by IntelliJ IDEA.
User: peikunkun
Date: 2017/12/30 0030
Time: 下午 9:29
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String contextPath = request.getContextPath();
String realPath = request.getSession().
getServletContext().getRealPath("/");
String basePath = request.getScheme() + "://" + request.getServerName() + ":" +
request.getServerPort() + contextPath + "/";
%>
<html>
<head>
<title>Title</title>
</head>
<body>
文件上传的jsp页面<br>
${message}
<form method="post" enctype="multipart/form-data" action='<%=basePath%>fileController/uploadFile.do'>
文件描述:<input type="text" name="filedesc"/><br/>
文件描述:<input type="file" name="uploadFile"/><br/>
<input type="submit" value="提交"/><br/>
</form>
</body>
</html>
3.文件上传之后的业务处理类
@RequestMapping(value = "fileController")
@Controller
public class FileController {
@RequestMapping(value = "uploadFile", method = RequestMethod.POST)
public String uploadFile(HttpServletRequest request, @RequestParam(value = "filedesc", required = false) String fileDesc, @RequestParam(value = "uploadFile") MultipartFile file, Model model) {
if (!file.isEmpty()) {
System.out.println("文件正确");
String path = request.getContextPath();
System.out.println("路径为:" + path);
/*文件原始名称*/
String fileName = file.getOriginalFilename();
File newFile = new File(path, fileName);
if (!newFile.getParentFile().exists()) {
newFile.getParentFile().mkdirs();
}
try {
path = "F:" + File.separator + "测试文件夹";
/*输出到一个新的文件夹中,具体api见下面*/
file.transferTo(new File(path + File.separator + fileName));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("保存成功");
model.addAttribute("result", "储存成功");
} else {
model.addAttribute("result", "储存失败");
System.out.println("文件错误");
}
return "/fileupload/uploadresult";
}
}
4.文件上传时以对象的方式进行上传文件(对象要序列化)
1.只需要将要上传的文件的属性类型设置为MultipartFile类型的,如:
/*上传文件类型设置为MultipartFile上传时,会自动绑定*/
private MultipartFile image;
public MultipartFile getImage() {
return image;
}
public void setImage(MultipartFile image) {
this.image = image;
}
2.jsp页面需要与实体类的对象名称一样
用户头像:<input type="file" name="image"/><br/>
3. action的处理类中可以使用@ModelAttribute UserRegister userRegister进行接收数据,映射数据。
@RequestMapping(value = "userRegister")
public String userRegister(HttpServletRequest request, @ModelAttribute UserRegister userRegister, Model model) {}
5.transferTo()方法的api
文件的下载
下载的原理就是使用jsp页面传递文件名称给后台,后台使用Apache Commons FileUpload 组件的FileUtils读取项目的images文件下的该文件,然后将其构成ResponseEntity对象返回给客户端。
使用ResponseEntity对象可以很方便的设置HttpHeaders和HttpStatus,下面代码中的MediaType代表的是Internet Media Type,也叫做MIME类型,即互联网媒体。
RequestMapping(value = "download")
public ResponseEntity<byte[]> downloadFile(HttpServletRequest request, @RequestParam(value = "filename", required = true) String filename, Model model) throws IOException {
String path = path = "F:" + File.separator + "测试文件夹";
File file = new File(path + File.separator + filename);
HttpHeaders httpHeaders = new HttpHeaders();
/*下载时的文件,解决中文乱码*/
String downFileName = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
/*通知浏览器以attachment方式打开图片*/
httpHeaders.setContentDispositionFormData("attachment", downFileName);
/*二进制流数据(下载最长见的方式)*/
httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
/*设置http的协议状态和设置相应的Context-Type*/
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), httpHeaders, HttpStatus.CREATED);
}
SpringMVC拦截器
Interceptor拦截器也是SpringMVC的中重要组成部分,他的作用主要是拦截用户的请求并做出相应的处理,比如进行用户权限验证,判断用户是否登录等。
SpringMVC的拦截器是可插拔式拦截器,如果用户项应用某个拦截器,可以在配置文件中开启该拦截器就可以,不想用就取消,不会影响SpringMVC框架造成影响。
1.Interceptor拦截器的接口api
2.拦截器类
package com.pkk.handlerInterceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Created by peikunkun on 2018/1/8 0008.
*/
/*继承extends HandlerInterceptorAdapter和实现HandlerInterceptor都可以*/
public class AuthorizationInterceptor implements HandlerInterceptor {
/*不拦截以下请求*/
private static final String[] IGNORE_URL = {"/loginResult", "userLogin"};
/**
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @return
* @throws Exception
* @Desc 处理拦截器使用,在Controller之前调用,该方法返回true才会继续执行,返回false方法直接结束,不在进行后续操作
*/
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
return false;
}
/**
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param modelAndView
* @throws Exception
* @Desc 该方法只有在Controller的方法调用之后执行,可以对方法返回的ModelAndView进行操作,该方法也只能在当前的Interceptor的preHandle返回true时才会执行
*/
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle 开始执行了");
}
/**
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e
* @throws Exception
* @Desc 该方法在整个请求之后完成执行,主要作用是清理资源
* 该方法只有会在preHandle方法返回true时才会执行
*/
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion 开始执行了");
}
}
3.配置拦截器并启用拦截器
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截所有的请求-->
<mvc:mapping path="/*"/>
<!--启用拦截器-->
<bean class="com.pkk.handlerInterceptor.AuthorizationInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>