在Spring MVC中实现文件上传的方式有两种:
- 通过 Apache Commons 的 FileUpload 组件实现
- 通过 Servlet 的内置支持
一、我们先看一看需要了解的内容
1、视图页面
为了上传文件,必须将form表单的 enctype 属性设置为 multipart/form-data,如下例子:
<form enctype="multipart/form-data" method="post" action="/save-resource">
<input type="file" name="images" />
<input type="submit" name="upload" />
</form>
表单中包含一个类型为 file 的 input 标签,被浏览器解析后会显示成一个文件上传的按钮,若要上传多个文件,就准备多个 file 类型的 input 标签
在 HTML5 中,如果需要上传多个文件,则文件上传控件需要设置一个 multiple 属性,如下三种形式皆可。
<input type="file" multiple />
<input type="file" multiple="multiple" />
<input type="file" multiple="" />
2、MultipartFile 接口
上传到 Spring MVC 应用程序的文件会被包在一个 MultipartFile 对象中,
于是我们可以通过 MultipartFile 对象的方法来获取文件,常用三个方法如下:
- Stirng getOriginalFilenam( ) 在客户端的文件系统中返回原始文件名。
- long getSize( ) 以字节为单位获取文件的大小
- void transferTo( File dest ) 将收到的文件传输到给定的目标文件
要想查看官方文档的话点这里👈
二、具体的实现过程
1、创建工程
这里我们创建了一个 maven 工程,并使用了一个简单的 webapp 模板。这样会自动生成 webapp 目录,web.xml等文件,点击 Next 进入下一步。
如图所示,按自己需求填写 groupId ArtifactId,version 就按默认来吧,点击 Next 进入下一步。
接下来有关 maven 仓库按默认走,点击 Next 进入下一步。
填写项目名称后点击 Finish 建立项目工程。
等待 maven 加载完毕,工程目录如下:
2、准备SpringMVC
(1) 目录文件调整
首先准备几个文件,在 main 下创建一个 java 文件夹和一个 resource 文件夹。
为了视图页面不被直接访问,在 WEB-INF 下创建一个 views 文件夹专门用来存放视图文件(比如jsp),将原有的 index.jsp 文件删除或移动到 views 目录下。
找到导航栏点击 File->Project Structure->Modules,
将 java 文件设为 Source(蓝色的),将 resource 文件设为 Resources(灰色的)
点击OK或者Apply
(2) 编辑pom.xml
设置配置属性值,找到<properties>标签,在其中添加 <spring.version> 4.3.7.RELEASE </spring.version>
统一设置spring相关jar包版本,如下所示
<properties>
<spring.version>4.3.7.RELEASE</spring.version>
...
</properties>
找到<dependencies> ,在其中添加所需的依赖,如文件上传所需的commons-io 、commons-fileupload
<dependencies>
<!-- javaee-->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
<!-- commons-os-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
...(spring其他包省略)
</dependencies>
(3) 编辑web.xml
在<web-app>标签内部添加如下代码,
用以设置编码、spring MVC调度器,设定springmvc的相关配置文件路径
<!--过滤器设置编码-->
<filter>
<filter-name>CharacterEncodingFilter</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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
(4) 编辑spring-mvc.xml
在 resourece 文件下新建一个spring-mvc.xml文件,用以配置spring容器中的bean。
在这里,我们配置了视图解析器,multipartResovler,以及扫描控制器目录的配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- 启用注解映射-->
<mvc:annotation-driven/>
<!--scan controller-->
<context:component-scan base-package="cn.bps.controller"/>
<!--静态资源images下的文件可以通过context/images/xx来访问-->
<mvc:resources mapping="/images/**" location="/images/" />
<!-- multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="6000000"/>
</bean>
<!--viewResolver-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
(5) 新建domain类
新建的domain类用来封装上传文件的相关信息。
package cn.bps.domain;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public class Product {
private List<MultipartFile> images;
//getter and setter
}
(6) 新建controller类
package cn.bps.controller;
import ...
@Controller
public class ProductController {
@RequestMapping(value = "/upload")
public ModelAndView upload(){
return new ModelAndView("index");
}
@RequestMapping(value = "/save-resource", method = RequestMethod.POST)
public String saveResource(HttpServletRequest request,
@ModelAttribute Product product, Model model){
List<MultipartFile> files = product.getImages();
if(files != null && files.size() > 0){
for(MultipartFile multipartFile : files){
File imageFile = new
File(request.getServletContext().getRealPath("/images"),fileName);
System.out.println("文件存储在--> "+imageFile.getPath());
try{
multipartFile.transferTo(imageFile);
}catch (IOException e){
e.printStackTrace();
System.out.println("文件保存失败");
}
}
}
//model.addAttribute("product",product); //我们不需要写这句
return "show";
}
}
👇在这里,saveResource 方法有三个参数:
- HttpServletRequest
- Product
- Model
public String saveResource(HttpServletRequest request, @ModelAttribute Product product, Model model)
Spring MVC 在每次调用请求处理方法是,都会创建一个 Model 类型的实例,若打算使用该实例,就在方法中添加一个 Model 类型的参数。
@ModelAttribute 注解了方法参数,那么被注释的 参数实例就会被添加到 Model 对象中。在这里, Product 实例被添加。
就像上面介绍的那样,我们用 MultipartFile 的transferTo
方法,将文件存储在本地。说是本地,其实是存储在项目根目录对应的位置,也就是tomcat下的 webapps 目录下的项目目录。在我的电脑上是这个路径👇,其中 FileUpload 是项目名,jkqla5.png 是文件名。
D:\Env\Appache-Tomcat\apache-tomcat-9.0.22\webapps\FileUpload\images\jkqla5.png
三、说的差不多了,我们run一下看下😂
找到右上角如上图所示,点击 Edit Confirguarations...
这时候打开了一个窗口 Run/Debug Configurations ,点击左上角的 + 号找到 Tomcat Server ,选择 Local ,点击 Configure 配置本地tomcat。
点击 Development,看到新的窗口,点击右上角加号添加artifact,如图所示选择之后点击 OK 完成选择。并在窗口下方设置 Application context,即webapp名称,这时我们访问的内容都需要加上前缀 / FileUpload,最后点击 OK 完成tomcat的配置。
在这里,我们选择了两张图片,点击上传提交之后,跳转至如下页面👇
该页面显示了上传的文件。
大功告成!!
至于显示图片的代码如下
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<c:forEach items="${product.images}" var="image">
<li>${image.originalFilename}</li>
<img src='<c:url value="/images/"/>${image.originalFilename}'/>
</c:forEach>
</body>
</html>
代码在👇
https://github.com/bps97/bps-springMVC/tree/master/FileUpload