一、 上传文件的简单步骤
1.所需jar包
除了spring的jar包外,需要添加commons-fileupload.jar这个jar包
2.修改spring的配置文件
要让springmvc支持文件上传,必须在spring的配置文件中增加下面的配置
<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<!-- 指定所上传文件的总大小,单位字节。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
<property name="maxUploadSize" value="1124000"/>
</bean>
3.前台html表单
<form enctype="multipart/form-data" method="post" action="uploadfile">
<input type="file" name="file"/>
<input type="submit" value="submit"/>
</form>
enctype=”multipart/form-data”是必须设置的属性
4.后台实现
@RequestMapping(value = "/uploadfile",method=RequestMethod.POST)
public ModelAndView uploadfileUpload(HttpServletRequest req,HttpServletResponse resp,MultipartFile file) throws Exception {
ModelAndView mo = new ModelAndView();
mo.addObject("filename",file.getOriginalFilename());
mo.addObject ("size", file.getSize()/(1024.0*1024) + "M");
return mo;
}
这个代码只是简单的返回了上传的文件名字和大小,只是一个示例。实际项目中可操作file对象将上传的文件保存在服务器上。
二、 配置上传文件超过maxUploadSize时跳转的页面
上面再配置文件中配置了上传文件的最大大小,当上传的文件超过最大大小时,spring就会抛出org.springframework.web.multipart.MaxUploadSizeExceededException异常,这个异常是在请求达到controller处理函数之前抛出的,可以通过修改spring配置文件来指定跳转页面,
在spring配置文件中增加如下配置:
<!-- SpringMVC在超出上传文件限制时,会抛出org.springframework.web.multipart.MaxUploadSizeExceededException -->
<!-- 该异常是SpringMVC在检查上传的文件信息时抛出来的,而且此时还没有进入到Controller方法中 -->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!-- 遇到MaxUploadSizeExceededException异常时,自动跳转到/view配置根目录/error_fileupload.jsp页面 -->
<prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">error_fileupload</prop>
</props>
</property>
</bean>
三、 使用ajax方式上传文件
上面介绍的是通过正常提交表单的方式进行文件的上传,有时需要通过ajax的方式进行文件的上传。本文介绍的是基于jquery的jquery.form.js这个插件来实现的ajax上传文件
1.前台页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
<script type="text/javascript" src="<c:url value='/resources/3rdparty/jquery/jquery-2.1.1.min.js'/>"></script>
<script type="text/javascript" src="<c:url value='/resources/3rdparty/jquery/jquery.form.js'/>"></script>
</head>
<body>
<div>
<div><span>文件名:</span><span>${filename }</span></div>
<div><span>文件大小:</span><span>${size }</span></div>
<form enctype="multipart/form-data" method="post" action="uploadfile">
<input type="file" name="file"/>
<input type="submit" value="submit"/>
</form>
</div>
<script type="text/javascript">
$(document).ready(function(){
$("form").submit(function(evt){
evt.preventDefault();
$("form").ajaxSubmit({
url:"uploadfile",
dataType:"json",
type:"POST",
success: function(data){
console.log("data",data);
},
error: function(error){
console.log("error",error);
}
});
});
});
</script>
</body>
</html>
2.后台处理
@RequestMapping(value = "/uploadfile",method=RequestMethod.POST)
@ResponseBody
public Map<String,Object> uploadfileUpload(HttpServletRequest req,HttpServletResponse resp,MultipartFile file) throws Exception {
Map<String,Object> map = new HashMap<String,Object>();
map.put("filename", file.getOriginalFilename());
map.put("size", file.getSize()/(1024.0*1024) + "M");
return map;
}
四、 获取文件上传进度
1.使用jquery.form.js插件获取上传进度
$("form").ajaxSubmit({
url:"uploadfile",
dataType:"json",
type:"POST",
uploadProgress: function(event,position,total,percentComplete){
console.log("event",event);
console.log("position",position);
console.log("total",total);
console.log("percentComplete",percentComplete);
},
success: function(data){
console.log("data",data);
},
error: function(error){
console.log("error",error);
}
});
Form插件的ajaxSubmit中的配置项uploadProgress就是用来获取文件上传进度的回调函数。注意这个回调函数中获取的是上传文件的总进度,也就是说同时上传多个文件时,这个回调中的参数信息是所有文件上传的总进度。
2.通过实现org.apache.commons.fileupload.ProgressListener接口
这种方式的原理是通过实现org.apache.commons.fileupload.ProgressListener接口的方法,继承org.springframework.web.multipart.commons.CommonsMultipartResolver重新实现相应的方法,将进度监听器设置到文件上传类中。进度监听器则将文件上传的进度信息保存在session中,这样前台请求进度信息时,后台就可以通过session获取。
1) 构造保存进度信息的实体类
可以根据自己的想要的信息自行设计
public class UploadFileProgressEntity {
private long pBytesRead = 0L;//已读的byte总数
private long pContentLength = 0L;//要读的文件总byte数,如果长度未知,值为-1
private int pItems=0;//当前所读文件的索引(从1开始),单文件上传时始终为1,0表示没有文件在读
public long getpBytesRead() {
return pBytesRead;
}
public void setpBytesRead(long pBytesRead) {
this.pBytesRead = pBytesRead;
}
public long getpContentLength() {
return pContentLength;
}
public void setpContentLength(long pContentLength) {
this.pContentLength = pContentLength;
}
public int getpItems() {
return pItems;
}
public void setpItems(int pItems) {
this.pItems = pItems;
}
}
2) 实现org.apache.commons.fileupload.ProgressListener接口
public class UploadFileProgressListener implements ProgressListener {
private HttpSession session;
public UploadFileProgressListener(HttpSession session) {
this.session = session;
UploadFileProgressEntity ps = new UploadFileProgressEntity();
session.setAttribute("uploadFileProgressEntity", ps);
}
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
UploadFileProgressEntity ps = (UploadFileProgressEntity)session.getAttribute("uploadFileProgressEntity");
ps.setpBytesRead(pBytesRead);
ps.setpContentLength(pContentLength);
ps.setpItems(pItems);
session.setAttribute("uploadFileProgressEntity", ps);
}
}
3) 重写类
org.springframework.web.multipart.commons.CommonsMultipartResolver
public class MyCommonsMultipartResolver extends CommonsMultipartResolver {
private HttpServletRequest request;
/**
* 初始化org.apache.commons.fileupload.servlet.ServletFileUpload实例
*/
protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {
ServletFileUpload upload = new ServletFileUpload(fileItemFactory);
upload.setSizeMax(-1);
if (request != null) {
HttpSession session = request.getSession();
UploadFileProgressListener uploadProgressListener = new UploadFileProgressListener(session);
upload.setProgressListener(uploadProgressListener);
}
return upload;
}
/**
* 将HttpServletRequest包装为MultipartHttpServletRequest,重载该方法获取HttpServletRequest,从而取得session
*/
public MultipartHttpServletRequest resolveMultipart(
HttpServletRequest request) throws MultipartException {
this.request = request;// 获取到request,要用到session
return super.resolveMultipart(request);
}
@SuppressWarnings("unchecked")
@Override
public MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
HttpSession session = request.getSession();
String encoding = "utf-8";
FileUpload fileUpload = prepareFileUpload(encoding);//这个函数内调用 newFileUpload()
UploadFileProgressListener uploadProgressListener = new UploadFileProgressListener(session);
fileUpload.setProgressListener(uploadProgressListener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
} catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
} catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
}
}
4) 后台获取进度信息
@RequestMapping(value = "/uploadfile/progess",method=RequestMethod.GET)
@ResponseBody
public Map<String,Object> uploadfileUploadProgress(HttpServletRequest req,HttpServletResponse resp) throws Exception {
HttpSession session = req.getSession();
UploadFileProgressEntity ps = (UploadFileProgressEntity)session.getAttribute("uploadFileProgressEntity");
Map<String,Object> map = new HashMap<String,Object>();
if (null == ps) {
map.put("progress", "");
} else {
map.put("progress", ps);
}
return map;
}
5) 前台获取进度信息
$(document).ready(function(){
window.getProgess = function(){
$.ajax({
type: "GET",
url: "uploadfile/progess",
success: function(data){
console.log("progess",data);
}
});
};
window.getProgressTimer = null;
$("form").submit(function(evt){
evt.preventDefault();
$("form").ajaxSubmit({
url:"uploadfile",
dataType:"json",
type:"POST",
beforeSubmit: function(){
window.getProgressTimer = setInterval("window.getProgess()",1000);
},
/*uploadProgress: function(event,position,total,percentComplete){
console.log("event",event);
console.log("position",position);
console.log("total",total);
console.log("percentComplete",percentComplete);
},*/
success: function(data){
console.log("data",data);
clearInterval(window.getProgressTimer);
},
error: function(error){
console.log("error",error);
clearInterval(window.getProgressTimer);
}
});
});
});
6) 修改Spring配置文件
在上面说到了Spring上传文件要增加org.springframework.web.multipart.commons.CommonsMultipartResolver类的bean的配置,这里重写了这个类,所以要将这个bean配置为重写的类:
<bean id="multipartResolver" class="cn.com.helloword.util.uploadfile.MyCommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"/>
<!-- 指定所上传文件的总大小,单位字节。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
<property name="maxUploadSize" value="1073741824"/>
</bean>