Spring MVC FileUpload 文件上传、显示

Spring MVC中实现文件上传的方式有两种:

  • 通过 Apache CommonsFileUpload 组件实现
  • 通过 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>

表单中包含一个类型为 fileinput 标签,被浏览器解析后会显示成一个文件上传的按钮,若要上传多个文件,就准备多个 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 ArtifactIdversion 就按默认来吧,点击 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 实例被添加。

就像上面介绍的那样,我们用 MultipartFiletransferTo方法,将文件存储在本地。说是本地,其实是存储在项目根目录对应的位置,也就是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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容