SpringMVC 学习笔记 Part5
1. 文件上传的原理
本小节将回顾 JavaWeb 传统的文件上传方式和学习更为方便的 SpringMVC 提供的文件上传组件。首先先来回顾一下文件上传的一些前置知识。
- form 表单的 enctype 取值必须是:multipart/form-data (默认值是:application/x-www-form-urlencoded) ,enctype 是表单请求正文的类型,multipart属性表示请求正文将被分成好几个部分。
- form 表单的 method 属性取值必须是 Post 。
- form 表单中需提供一个文件选择域< input type=“file” />
<form action="user/fileupload" method="post" enctype="multipart/form-data">
选择文件:<input type="file" name="upload"/><br/>
<input type="submit" value="上传文件"/>
</form>
注:当 form 表单的 enctype 取值不是默认值后,request.getParameter()将失效。
当 form 表单的 enctype 取值为 ”application/x-www-form-urlencoded” 时,form 表单的正文内容是:key=value&key=value&key=value 。
当 form 表单的 enctype 取值为 “Mutilpart/form-data” 时,请求正文内容就变成每一部分都是 MIME 类型描述的正文:分解符、协议头、协议的正文以及协议的类型(MIME类型)。
2. 传统的文件上传
首先先导入文件上传相关的坐标。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
编写文件上传的控制器方法。
@RequestMapping(value="/myUpload")
public String myUpload(HttpServletRequest request) throws Exception {
// 先获取到要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File对象,一会向该路径下上传文件
File file = new File(path);
// 判断路径是否存在,如果不存在,创建该路径
if(!file.exists()) {
file.mkdirs();
}
// 创建磁盘文件项工厂,再使用工厂创建文件上传解析器
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 解析request对象,得到了文件项的集合
List<FileItem> items = fileUpload.parseRequest(request);
// 遍历
for (FileItem item : items) {
// 判断文件项是普通字段,还是上传的文件
if(item.isFormField()) {
//说明是普通表单项
}else {
// 说明是上传文件项
// 获取到上传文件的名称
String filename = item.getName();
// 把文件的名称唯一化
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
filename = uuid+"_"+filename;
// 上传文件
item.write(new File(file, filename));
// 删除临时文件(当不超过10kb时,上传完服务器会自动清除。而当超过10kb时,上传完文件将会有临时文件,需要自行清除)
item.delete();
}
}
return "success";
}
3. SpringMVC框架的文件上传
首先简述一下SpringMVC框架的文件上传的基本原理:首先需要有一个框架为我们提供的 MultipartFile 类对象。当我们点击 submit 提交后,request 将会被发送到前端控制器中,前端控制器将 request 送入配置文件解析器进行解析,解析完成会返回一个 upload文件上传项 给前端控制器,前端控制器再把这个 upload 送到 Controller 里我们编写的方法里。
MultipartFile 类对象如何创建也非常简单。第一步先在 xml 里配置创建进 IoC 容器里,其次只要加入我们编写文件上传的控制器方法中的形参里就好啦。
第一步:创建CommonsMultipartResolver进IoC容器。
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10485760"/>
</bean>
注意此处CommonsMultipartResolver的bean创建,id属性值必须为multipartResolver,为其他的将会造成HTTP 500错误。
第二步:编写文件上传的控制器方法中加入MultipartFile的形参,并编写文件上传代码。
@RequestMapping("myUpload")
public String myUpload(HttpServletRequest request,MultipartFile upload) throws Exception {
// 先获取到要上传的文件目录
String path = request.getSession().getServletContext().getRealPath("/uploads");
// 创建File对象,一会向该路径下上传文件
File file = new File(path);
// 判断路径是否存在,如果不存在,创建该路径
if (!file.exists()) {
file.mkdirs();
}
// upload是被springmvc解析完成的,是可以直接使用的上传文件项
// 改动1.获取到上传文件的名称
String filename = upload.getOriginalFilename();
// 把文件的名称唯一化
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
filename = uuid + "_" + filename;
// 改动2.完成文件上传
upload.transferTo(new File(path,filename));
return "success";
}
与传统的文件上传方式相比,共简化了两处代码,也省去了遍历操作。