Spring MVC-09循序渐进之文件上传(基于Apache Commons FileUpload)
概述
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
- 点赞
- 收藏
- 关注作者
评论(0)