一、前提条件
1、表单的要求
- method=”post”
- 编码方式 enctype=”multipart/form-data”
- 文件上传框 input type=”file”
1 2 3
| <form action="..." method="post" enctype="multipart/form-data"> <input type="file" ... /> </form>
|
2、额外导入的 jar 包
在 Spring MVC 的 jar 包基础上导入
commons-fileupload-1.3.jar
commons-io-2.0.1.jar
3、配置 CommonsMultipartResolver
1 2 3 4 5
| <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"/> </bean>
|
4、接收数据
① 普通数据:和以前一样正常接收
② 文件数据:使用@RequestParam 注解注入到 MultipartFile 类型的入参中
1 2 3 4
| @RequestMapping("/upload") public String upload(@RequestParam("picture") MultipartFile picture) { return "..."; }
|
③ Alt+7 查看 MultiPartFile 类型里面的方法,看看通过这个接口我们可以得到哪些数据
二、实验测试
- 配置 spring-mvc 的配置文件
- 配置 web.xml 配置前端控制器
- 配置 index.jsp 页面
- 配置控制器 UploadController 类
1、配置 spring-mvc.xml 配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <context:component-scan base-package="com.atguigu.upload.controller"/>
<mvc:annotation-driven/>
<mvc:default-servlet-handler/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"> <property name="prefix" value="/WEB-INF/pages/"/> <property name="suffix" value=".jsp"/> </bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
</bean>
|
2、web.xml
1 2 3 4 5 6 7 8 9 10 11 12 13
| <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
|
3、index.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <html> <head> <title>文件上传</title> </head> <body> <form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data" > 用户名:<input type="text" name="userName" /><br /> 头像:<input type="file" name="headPicture" /><br />
<button type="submit">保存</button> </form> </body> </html>
|
4、UploadController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| @Controller public class UploadController {
@Autowired private ServletContext servletContext;
@RequestMapping("/upload") public String doUpload( // 正常获取普通表单项 @RequestParam("userName") String userName,
// 使用MultipartFile类型获取文件上传表单项 @RequestParam("headPicture")MultipartFile headPicture,
Model model ) throws IOException {
System.out.println("userName = " + userName);
String inputName = headPicture.getName(); System.out.println("inputName = " + inputName);
String originalFilename = headPicture.getOriginalFilename(); System.out.println("originalFilename = " + originalFilename);
String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileName = System.currentTimeMillis() +extName; System.out.println("fileName = " + fileName);
String contentType = headPicture.getContentType(); System.out.println("contentType = " + contentType);
boolean empty = headPicture.isEmpty(); System.out.println("empty = " + empty);
long size = headPicture.getSize(); System.out.println("size = " + size);
byte[] bytes = headPicture.getBytes(); System.out.println("bytes = " + Arrays.asList(bytes));
InputStream inputStream = headPicture.getInputStream(); System.out.println("inputStream = " + inputStream);
String virtualPath = "/hello";
String targetDirPath = servletContext.getRealPath(virtualPath);
File targetFile = new File(targetDirPath + "/" + fileName);
headPicture.transferTo(targetFile);
String picPath = servletContext.getContextPath() + "/hello/" + fileName;
model.addAttribute("picPath", picPath);
return "target"; }
|
三、扩展
1、上传请求诡异重定向问题
当 Web 应用中某个目录的访问路径和@RequestMapping 匹配的路径雷同时,会导致无法正常访问。所以为了避免这种情况,一定要让各种资源独立命名,有各自不同的访问地址。
2、关于已上传文件的保存
① 保存到 Tomcat 服务器上的缺陷
- 当用户上传文件非常多的时候,拖慢 Tomcat 运行的速度
- 当 Web 应用重新部署时,会导致用户以前上传的文件丢失
- 当 Tomcat 服务器以集群的形式运行时,文件不会自动同步
② 建议的解决方案
- 自己搭建文件服务器,例如:FastDFS 等
- 第三方文件服务
3、同时上传多个文件
① 表单
1 2 3 4 5 6 7 8 9
| <form action="${pageContext.request.contextPath}/upload/multi/file" method="post" enctype="multipart/form-data" > 文件1:<input type="file" name="picture" /><br /> 文件2:<input type="file" name="picture" /><br /> <button type="submit">保存</button> </form>
|
②Java 代码
使用 List<MultipartFile>类型接收即可
1 2 3 4 5 6 7 8 9 10
| @RequestMapping("/upload/multi/file") public String multiFile(@RequestParam("picture")List<MultipartFile> fileList) {
for (MultipartFile multipartFile : fileList) { String originalFilename = multipartFile.getOriginalFilename(); System.out.println("originalFilename = " + originalFilename); }
return "target"; }
|