说明:
文件上传的途径
文件上传主要有两种方式:
1.使用Apache Commons FileUpload元件。
2.利用Servlet3.0及其更高版本的内置支持。
客户端编程
1.为了上传文件,必须将HTML表格的enctype属性值设为multipart/form-data,像下面这样:
1
2
3
4
|
<form action= "action" enctype= "multipart/form-data" method= "post" >
Select a file<input type= "file" name= "fieldName" />
<input type= "submit" value= "Upload" />
</form>
|
2.在HTML5之前,如果要想上传多个文件,必须使用多个文件input元素。但是,在HTML5中,通过在input元素中引入多个multiple属性,使得多个文件的上传变得更加简单,下面均可使一个上传框支持多个文件上传。
1
2
3
|
<input type= "file" name= "fieldName" multiple/>
<input type= "file" name= "fieldName" multiple= "multiple" />
<input type= "file" name= "fieldName" multiple= "" />
|
MultipartFile接口
在SpringMVC中处理已经上传的文件十分简单,上传到SpringMVC应用程序中的文件会被包在一个MultipartFile对象中,你唯一要做的事情就是用类型为MultipartFile的属性编写一个Domain类。就像下面这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package domain;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
import java.util.List;
public class Product implements Serializable {
//实现了这个接口,可以安全的将数据保存到HttpSession中
private long id;
private String name;
private String description;
private String price;
//在Domain类中加入MultipartFile类型的属性,用来保存上传的文件
private List<MultipartFile> images;
public List<MultipartFile> getImages() {
return images;
}
public void setImages(List<MultipartFile> images) {
this .images = images;
}
......多个get和set方法。
|
MultipartFile接口提供了以下方法:
Modifier and Type | Method and Description |
---|---|
byte[] | getBytes()Return the contents of the file as an array of bytes. |
String | getContentType()Return the content type of the file. |
InputStream | getInputStream()Return an InputStream to read the contents of the file from. |
String | getName()Return the name of the parameter in the multipart form. |
String | getOriginalFilename()Return the original filename in the client's filesystem. |
long | getSize()Return the size of the file in bytes. |
boolean | isEmpty()Return whether the uploaded file is empty, that is, either no file hasbeen chosen in the multipart form or the chosen file has no content. |
void | transferTo(File dest)Transfer the received file to the given destination file. |
实例:用CommonsFileUpLoad上传文件
导入Jar包及配置环境变量
编写视图
代码:
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
|
<%@ taglib prefix= "form" uri= "http://www.springframework.org/tags/form" %>
<%@ page contentType= "text/html;charset=UTF-8" language= "java" %>
<html>
<head>
<title>Add Product Form</title>
</head>
<body>
<form:form action= "product_save" method= "post" commandName= "product" enctype= "multipart/form-data" >
<fieldset>
<legend>Add a Product</legend>
<p>
<label for = "name" >ProductName</label>
<form:input type= "text" id= "name" name= "name" tabindex= "1" path= "name" />
</p>
<p>
<label for = "description" >ProductDescription</label>
<form:input type= "text" id= "description" name= "description" tabindex= "2" path= "description" />
</p>
<p>
<label for = "price" >ProductPrice</label>
<form:input type= "text" id= "price" name= "price" tabindex= "3" path= "price" />
</p>
<p>
<label for = "image" >ProductImage</label>
<input type= "file" name= "images[0]" >
</p>
<p>
<input type= "reset" >
<input type= "submit" >
</p>
</fieldset>
</form:form>
</body>
</html>
|
说明:
首先为了上传文件,必须将HTML表格的enctype属性值设为multipart/form-data
其次,在HTML5之前,如果要想上传多个文件,必须要用到多个文件input元素。
但是在HTML5,通过在Input元素中引入过个multiple属性,使得多个文件上传变得更加简单。
1
2
3
|
<input type= "file" name= "fieldName" multiple/>
<input type= "file" name= "fieldName" multiple= "multiple" />
<input type= "file" name= "fieldName" multiple= "" />
|
图示:
编写控制器
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
|
package controller;
import domain.Product;
import Service.ProductService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.List;
@Controller
public class ProductController {
private static final Log logger=LogFactory.getLog(ProductController. class );
@Autowired
private ProductService productService;
@RequestMapping (value = "/product_input" )
public String inputProduct(Model model)
{
logger.info( "inputProduct called" );
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();
System.out.println( "文件数量是" +files.size());
if ( null !=files&&files.size()> 0 )
{
for (MultipartFile file:files)
{
String fileName=file.getOriginalFilename(); //获得文件名称
File imagFile = new File(servletRequest.getServletContext().getRealPath( "/image" ),fileName); try {
file.transferTo(imagFile); //用于将文件写到服务器本地
} catch (IOException e) {
e.printStackTrace();
}
}
}
model.addAttribute( "product" ,product);
return "ProductDetails" ;
}
@RequestMapping (value = "/product_view/{id}" )
public String viewProduct( @PathVariable Long id,Model model)
{
Product product =productService.get(id);
model.addAttribute( "product" ,product);
return "ProductDetails" ;
}
}
|
配置文件
你可以看到我们在SpringMVC的配置文件中配置了一个名为multipartResolver的Bean。
基于servlet的multipartresolver实现Apache Commons FileUpload 1.2或以上。
提供“maxuploadsize”、“maxinmemorysize”和“defaultencoding”设置bean的属性(继承commonsfileuploadsupport)
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
|
<?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">
<context:component-scan base- package = "controller" />
<context:component-scan base- package = "Service" />
<!--
<mvc:annotation-driven>元素注册用于支持基于注解的控制器的请求处理方法的Bean对象。
详解:https: //my.oschina.net/HeliosFly/blog/205343
-->
<mvc:annotation-driven></mvc:annotation-driven>
<bean id= "viewResolver"
class = "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name= "prefix" value= "/WEB-INF/view/" />
<property name= "suffix" value= ".jsp" />
</bean>
<!--resources 元素指示SpringMVC那些静态资源需要单独处理-->
<mvc:resources mapping= "/image/**" location= "/image/" />
<bean id= "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" >
<property name= "maxUploadSize" value= "2000000" />
</bean>
</beans>
|
说明:
resources 元素指示SpringMVC那些静态资源需要单独处理,此处我们要单独处理的是image,如果不单独处理而是经过dispatcher的话,就会发生404错误.
实例:用Servlet3及其更高版本上传文件
说明:
有了Servlet3,就不需要Commons FileUpload 和Commons IO元件了.因为在Servlet3中内置了上传文件的特性.
幸运的是Domain类和Controller类基本不变,我们仅仅需要修改一下配置文件。
配置文件:
修改Web.xml
我们可以看到实在dispatcher的基础上添加了配置项:multipart-config
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
|
<?xml version= "1.0" encoding= "UTF-8" ?>
<web-app xmlns= "http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version= "3.1" >
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener- class >org.springframework.web.context.ContextLoaderListener</listener- class >
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet- class >org.springframework.web.servlet.DispatcherServlet</servlet- class >
<load-on-startup> 1 </load-on-startup>
<multipart-config>
<max-file-size> 20848820 </max-file-size>
<!--上传内文件的最大容量-->
<max-request-size> 418018841 </max-request-size>
<!--表示多部分HTTP请求允许的最大容量-->
<file-size-threshold> 1048576 </file-size-threshold>
<!--超过这个容量将会被写到磁盘中-->
<location>/image/</location>
<!--要将已上传的文件保存到磁盘中的位置-->
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--Spring中文乱码拦截器-->
<filter>
<filter-name>setcharacter</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>setcharacter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
|
SpringMVC配置文件添加多部分解析器
1
2
|
MultipartResolver接口的标准实现,基于Servlet 3.0 部分API. To be added as "multipartResolver" bean to a Spring DispatcherServlet context, without any extra configuration at the bean level.
<bean id= "MultipartResolver" class = "org.springframework.web.multipart.support.StandardServletMultipartResolver" ></bean>
|
实例:为多文件上传添加一个进度条
说明:
我们关注的是HTML5 input元素的change事件,当input元素的值发生改变时,他就会被触发。其次,我们还关注XMLHttpRequest对象中添加progress事件。XMLHttpRequest自然是AJAX的骨架。当异步使用XMLHttpRequest对象上传文件的时候就会持续地触发progress事件,直到上传进度完成或者取消。通过轻松监听progress事件,可以轻松地检测文件上传操作的进度。
编写Domain和Controller
1.Domain:UploadFile
1
2
3
4
5
6
7
8
9
10
11
12
|
package domain;
import org.springframework.web.multipart.MultipartFile;
import java.io.Serializable;
public class UploadFile implements Serializable {
private MultipartFile multipartFile;
public MultipartFile getMultipartFile() {
return multipartFile;
}
public void setMultipartFile(MultipartFile multipartFile) {
this .multipartFile = multipartFile;
}
}
|
2.Controller:Html5FileUploadController类
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
|
package controller;
import domain.UploadFile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
@Controller
public class Html5FileUploadController {
private static final Log logger = LogFactory.getLog(Html5FileUploadController. class );
@RequestMapping ( "/html5" )
public String inputProduct()
{
return "html5" ;
}
@RequestMapping ( "/file_upload" )
public void saveFile(HttpServletRequest servletRequest, @ModelAttribute UploadFile file, BindingResult result)
{
MultipartFile multipartFile =file.getMultipartFile();
String filename =multipartFile.getOriginalFilename();
try {
File file1 = new File(servletRequest.getServletContext().getRealPath( "/image" ),filename);
multipartFile.transferTo(file1);
System.out.println( "已经写人本地文件:" +file1.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
编写HTML5页面
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
<%--
Created by IntelliJ IDEA.
User: zy
Date: 17 - 3 - 8
Time: 下午 10 : 01
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType= "text/html;charset=UTF-8" language= "java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<script>
var totalFileLength,totalUploaded,fileCount,filesUploaded;
function debug(s) { //输出调试信息
var debug = document.getElementById( 'debug' );
if (debug)
{
debug.innerHTML =debug.innerHTML+ '</br>' +s;
}
}
function onUploadComplete(e) { //当一个文件上传完成,紧接着开始调用下次upLoadNext();
totalUploaded+=document.getElementById( 'files' ).files[filesUploaded].size;
filesUploaded++;
debug( 'Complete' +filesUploaded+ " of " +fileCount);
debug( 'totalUploaded:' +totalUploaded);
if (filesUploaded<fileCount)
{
upLoadNext();
}
}
function onUploadFailed() {
alert( "Error uploading file" );
}
function onUploadProgress(e) { //当进度发生改变时,改变进度条
if (e.lengthComputable)
{
var percentComplete =parseInt((e.loaded+totalUploaded)* 100 /totalFileLength);
var bar = document.getElementById( "bar" );
bar.style.width=percentComplete+ "%" ;
bar.innerHTML =percentComplete+ "% complete" ;
}
else
{
debug( 'unable to compute' );
}
}
function upLoadNext() { //将XMLHttpRequest对象的progress事件添加到onLoadProgress并将load事件和error事件分别绑定到对应方法。
var xhr = new XMLHttpRequest();
var fd = new FormData();
var file =document.getElementById( 'files' ).files[filesUploaded];
fd.append( "multipartFile" ,file);
xhr.upload.addEventListener( "progress" ,onUploadProgress, false );
xhr.addEventListener( "load" ,onUploadComplete, false );
xhr.addEventListener( "error" ,onUploadFailed, false );
xhr.open( "POST" , "file_upload" );
debug( 'uploading' +file.name);
xhr.send(fd);
}
function onFileSelect(e) { //当选择的文件发生改变时,重新获取并打印现在所选的文件信息
var files =e.target.files;
var output=[];
fileCount =files.length;
totalFileLength = 0 ;
for (var i= 0 ;i<fileCount;i++)
{
var file =files[i];
output.push(file.name, '(' ,file.size, 'bytes' , ')' ,file.lastModifiedDate.toLocaleDateString());
output.push( "<br/>" );
debug( 'add' +file.size);
totalFileLength+=file.size;
}
document.getElementById( 'selectedFiles' ).innerHTML = output.join( '' );
debug( 'totalFileLength:' +totalFileLength);
}
function startUpload() { //当用户点击提交以后开始执行
totalUploaded=filesUploaded= 0 ;
upLoadNext();
}
window.onload=function () {
document.getElementById( 'files' ).addEventListener( 'change' ,onFileSelect, false );
document.getElementById( 'upLoadButton' ).addEventListener( 'click' ,startUpload, false );
}
</script>
</body>
<h1>Multipart File Uploads with Progress Bar</h1>
<div id= "bar" style= "height:100px;background: #33dd33;width: 0%" >
</div>
<form>
<input type= "file" id= "files" multiple>
<br>
<output id= "selectedFiles" ></output>
<input id= "upLoadButton" type= "button" value= "Upload" >
</form>
<div id= "debug" style= "height: 100%;border: 2px solid green;overflow: auto" >
</div>
</html>
|
说明:
progressBar div用于展示上传进度,debug div用于显示调试信息。
执行脚本时,第一件事就是为4个变量分配空间:totalFileLength,totalUploaded,fileCount,filesUploaded;
- totalFileLength:主要用于保存上传文件的总长度。
- totalUploaded:指示目前已经上传的字节数。
- fileCount:包含了要上传的文件数量。
- fileUploaded:指示了已经上传的文件数量。
以上所述是小编给大家介绍的SpringMVC文件上传功能实例解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/MrSaver/p/6524376.html