Spring MVC-09循序渐进之文件上传(基于Apache Commons FileUpload)

举报
小工匠 发表于 2021/09/11 01:17:30 2021/09/11
【摘要】 概述客户端编程MultipartFile接口利用Commons FileUpload上传文件Domain类控制器配置文件JSP页面部署及测试源码 概述 Servlet出现之...

概述

Servlet出现之前,文件上传的开发比较困难,主要涉及在服务端解析原始的HTTP响应。 03年Apache发布了开源的Commons FileUplaod组件,极大地提高了文件上传的开发效率。

经过很多年,Servlet的设计人员才意识到文件上传的重要性,最终文件上传还是成了Servlet3的内置特性。

因此,在SpringMVC中处理文件上传主要有两种方法

  • 利用Apache Commons FileUpload组件

  • 利用Servlet3.0及其更高版本的内置支持

本篇博文我们探讨利用Apache Commons FileUpload组件来实现文件的上传


客户端编程

为了上传文件,必须将HTML表格的enctype属性设置为 multipart/form-data

如下

<form action="action" enctype="multipart/form-data" method="post">
    Select a file<input type="file" name="fileName"/>
    <input type="submit" value="Upload"/>
</form>
  
 
  • 1
  • 2
  • 3
  • 4

表格中必须包含类型为file的一个input元素,它会显示成一个按钮,点击时会打开一个对话框,用来选择文件。

HTML之前,如果要上传多个文件,需要使用多个input元素。 但是HTML5中,通过input元素中一如多个multiple属性,使得多个文件的上传更加简单。 在HTML5中编写以下任意一行代码,遍可以生成一个按钮选择多个文件

<input type="file" name="fileName" multiple/>
<input type="file" name="fileName" multiple="multiple"/>
<input type="file" name="fileName" multiple=""/>
  
 
  • 1
  • 2
  • 3

MultipartFile接口

上传到Spring MVC应用程序中的文件会被包装在一个MultipartFile对象中,我们仅仅用类型为MultipartFile的属性编写一个domain类即可

接口方法如下

这里写图片描述


利用Commons FileUpload上传文件

只有实现了Servlet3.0及其更高版本规范的Servlet容器,才支持文件上传。 对于低于Servlet3.0的容器,则需要使用Apache Commons FileUpload组件

maven依赖如下

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>
  
 
  • 1
  • 2
  • 3
  • 4
  • 5

我们使用1.3.1的版本


Domain类

我们的dimain类 Product,有一个类型为List< MultipartFile >的images属性

package com.artisan.domain;

import java.io.Serializable;
import java.util.List;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.NotBlank;
import org.springframework.web.multipart.MultipartFile;

public class Product implements Serializable {

    private static final long serialVersionUID = -5379168879247929742L;

    @NotBlank
    @Size(min = 1, max = 10)
    private String name;
    private String description;
    private float price;
    //在Domain类中加入MultipartFile类型的属性,用来保存上传的文件
    private List<MultipartFile> images;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public List<MultipartFile> getImages() {
        return images;
    }

    public void setImages(List<MultipartFile> images) {
        this.images = images;
    }

}

  
 
  • 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

控制器

控制器有两个处理请求的方法,inputProduct方法向浏览器返回一个产品表单,saveProduct方法将上传的文件保存到指定目录下

package com.artisan.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import com.artisan.domain.Product;

@Controller
@RequestMapping("/product")
public class ProductController {

    private static final Logger logger = Logger.getLogger(ProductController.class);

    @RequestMapping(value="/product_input",method=RequestMethod.GET)
    public String inputProduct(Model model){
        model.addAttribute("product",new Product());
        return "ProductForm";
    }


    @RequestMapping(value="/product_save",method=RequestMethod.POST)
    public String saveProduct(HttpServletRequest servletRequest,@ModelAttribute Product product,
            BindingResult bindingResult, Model model) {

        List<MultipartFile> files = product.getImages();
        List<String> fileNames = new ArrayList<String>();

        if (null != files && files.size() > 0) {
            for (MultipartFile multipartFile : files) {

                String fileName = multipartFile.getOriginalFilename();
                logger.info("fileName:" + fileName);
                fileNames.add(fileName);

                // 上传后的文件保存目录及名字
                File imageFile = new File("D:/", fileName);
                try {
                    // 转存文件
                    multipartFile.transferTo(imageFile);
                    logger.info("save image successfully");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // save product here
        model.addAttribute("product", product);
        return "ProductDetails";
    }

}

  
 
  • 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

保存文件只需要在MultipartFile调用transferTo方法即可,非常便捷简单。


配置文件

<?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:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd     
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 扫描控制层的注解,使其成为Spring管理的Bean -->
    <context:component-scan base-package="com.artisan.controller" />

    <!-- 静态资源文件 -->
    <mvc:annotation-driven />
    <mvc:resources mapping="/css/**" location="/css/" />
    <mvc:resources mapping="/*.jsp" location="/" />

    <!-- 视图解析器 -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>



       <!--1 CommonsMultipartResolver
            第一个需要使用 Apache 的 commons-fileupload 等 jar 包支持,
              但它可以在 servlet3.0以下的 版本中使用-->

    <!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
     <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="2000000"/>
        <property name="defaultEncoding" value="utf-8"/>
        <property name="maxInMemorySize" value="40960"/>
    </bean>


</beans>
  
 
  • 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

利用multipartResolver bean中的各种属性设置合理的文件上传限制条件。


JSP页面

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<html>
<head>
<title>Add Product Form</title>
<style type="text/css">@import url("<c:url value="/css/main.css"/>");</style>
</head>
<body>

<div id="global">
<form:form commandName="product" action="product_save" method="post" enctype="multipart/form-data">
    <fieldset>
        <legend>Add a product</legend>
        <p>
            <label for="name">Product Name: </label>
            <form:input id="name" path="name" cssErrorClass="error"/>
            <form:errors path="name" cssClass="error"/>
        </p>
        <p>
            <label for="description">Description: </label>
            <form:input id="description" path="description"/>
        </p>
        <p>
            <label for="price">Price: </label>
            <form:input id="price" path="price" cssErrorClass="error"/>
        </p>
        <p>
            <label for="image">Product Image: </label>
            <input type="file" name="images[0]"/> 
        </p>
        <p id="buttons">
            <input id="reset" type="reset" tabindex="4">
            <input id="submit" type="submit" tabindex="5" 
                value="Add Product">
        </p>
    </fieldset>
</form:form>
</div>
</body>
</html>

  
 
  • 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
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<html>
<head>
<title>Save Product</title>
<style type="text/css">@import url("<c:url value="/css/main.css"/>");</style>
</head>
<body>
<div id="global">
    <h4>The product has been saved.</h4>
    <p>
        <h5>Details:</h5>
        Product Name: ${product.name}<br/>
        Description: ${product.description}<br/>
        Price: $${product.price}
        <p>Following files are uploaded successfully.</p>
        <ol>
        <c:forEach items="${product.images}" var="image">
            ${image.originalFilename}
        </c:forEach>
        </ol>
    </p>
</div>
</body>
</html>
  
 
  • 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

部署及测试

这里写图片描述

这里写图片描述

看到目标目录D盘:

这里写图片描述

上传成功。


源码

代码已提交到github

https://github.com/yangshangwei/SpringMvcTutorialArtisan

文章来源: artisan.blog.csdn.net,作者:小小工匠,版权归原作者所有,如需转载,请联系作者。

原文链接:artisan.blog.csdn.net/article/details/79450224

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。