1.1简介
文件上传下载是很多web应用程序必不可少的功能点,比方说大家经常遇到的上传图像,上传简历,邮箱中添加附件等等。Springmvc结合Commons FileUpload能很容易进行文件上传下载后者是使用最为广泛的Java文件上传组件。
2.2 案例开发步骤
步骤一:在myeclipse8.6中新建web工程mvcfile,拷贝如下包到lib目下:
步骤二:编写web.xml 配置文件,代码如下:
=================================web.xml========================
<?xmlversion="1.0" encoding="UTF-8"?>
<web-appversion="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!-- 配置spring的字符集过滤 -->
<filter>
<filter-name>encode</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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encode</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
================================================================
步骤三:建立index.jsp,如下所示:
=========================index.jsp==============================
<%@ page language="java" import="java.util.*"pageEncoding="UTF-8"%>
<%
String path =request.getContextPath();
String basePath =request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>文件上传下载</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<script type="text/javascript"src="js/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(e){
$("[value=开始上传]").click(function(e){
var userName=$("[name=userName]").val();
if(userName==""){
window.alert("用户名不为空");
return;
}
vartheFile=$("[name=theFile1]").val();
if(theFile==""){
window.alert("文件名不为空");
return;
}
vartheSubfix=theFile.substr(theFile.lastIndexOf('.')+1);
theSubfix=theSubfix.toLowerCase();
window.alert("ttt:"+theSubfix);
varsubfixs=["png","gif","jpg","jpeg","bmp"];
varflag=false;
for(var i=0;i<subfixs.length;i++){
if(subfixs[i]==theSubfix){
flag=true;
break;
}
}
if(!flag){
window.alert("文件格式错误!");
return;
}
$("[name=myFrm]").submit();
});
});
</script>
</head>
<body>
<h1>文件上传演示</h1>
<form action="Upload.php"name="myFrm" method="post"enctype="multipart/form-data">
<table border="1px">
<tr><td>请输入用户名:</td><td><input type="text"name="userName"/></td></tr>
<!-- 第一个文件限定为图片 -->
<tr><td>请选择文件:</td><td><input type="file"name="theFile1"/></td></tr>
<tr><td>请选择文件:</td><td><input type="file"name="theFile2"/></td></tr>
<tr><td colspan="2"><input type="button" value="开始上传"/></td></tr>
</table>
</form>
</body>
</html>
=====================================================================
注意事项:form表单的method属性必须设置为post,并且要设置属性enctype="multipart/form-data",该属性的作用是表示该表单是文件上传表单。
步骤四:编写文件上传控制器类:
=========================UploadControl.java=========================
public class UploadControlimplements Controller{
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String userName=request.getParameter("userName");
HttpSession session=request.getSession();
//获得文件请求对象
MultipartHttpServletRequestmRequest=(MultipartHttpServletRequest)request;
String targetPath=session.getServletContext().getRealPath("/")+"uploads\\";
System.out.println("path:"+targetPath+",userName:"+userName);
File targetDir=new File(targetPath);
if(!targetDir.exists()){
targetDir.mkdirs();
}
//键是文件表单的名称,值是文件对象
Map<String, MultipartFile> fileMap =mRequest.getFileMap();
Set<String> keys=fileMap.keySet();
FileOutputStream fos=null;
String srcName="";
List<String> nameList=new ArrayList<String>();
//对上传的文件进行处理,如果有多个文件表单则处理多次
for(String key : keys){
//原始文件名
srcName=fileMap.get(key).getOriginalFilename();
nameList.add(srcName);
//获得输出流
fos=new FileOutputStream(targetPath+srcName);
//把输入流拷贝到输出流
FileCopyUtils.copy(fileMap.get(key).getInputStream(),fos);
}
request.setAttribute("userName", userName);
request.setAttribute("nameList", nameList);
return new ModelAndView("ShowFile");
}
}
=====================================================================
知识讲解:1. StringuserName=request.getParameter("userName")这句是表示获得普通表单参数。
2. MultipartHttpServletRequestmRequest=
(MultipartHttpServletRequest)request;这句是获得文件上传请求对象,通过该对象可以直接获得文件上传的参数,具体请看代码下面的的注释。
3. StringtargetPath=session.getServletContext()
.getRealPath("/")+"uploads\\";这句表示获得上传路径。例如:如果该项部署在服务器的C:\tomcat6.0.37\webapps\mvcfile下,那么targetPath的值是C:\tomcat6.0.37\webapps\mvcfile\uploads\。
4. 最后通过return new ModelAndView("ShowFile");转到ShowFile.jsp。
步骤五:建立ShowFile.jsp,如下所示:
=========================ShowFile.jsp===============================
<body>
<h2>上传人:${requestScope.userName}</h2>
<c:if test="${not empty requestScope.nameList}">
<c:forEach items="${requestScope.nameList}" var="oneName">
<h2>文件名:${oneName } <a href="Download.php?fileName=${oneName }">下载</a></h2>
</c:forEach>
</c:if>
</body>
=====================================================================
步骤六:在核心配置文件springmvc-servlet.xml里面完善如下配置
======================== springmvc-servlet.xml=======================
<beans>
<bean id="simpleUrlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/Upload.php">uploadControl</prop>
<prop key="/Download.php">downloadControl</prop>
</props>
</property>
</bean>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"value="/"></property>
<property name="suffix"value=".jsp"></property>
</bean>
<!-- SpringMVC在超出上传文件限制时,会抛出
org.springframework.web.multipart.MaxUploadSizeExceededException -->
<!-- 该异常是SpringMVC在检查上传的文件信息时抛出来的,
而且此时还没有进入到Controller方法中 -->
<!--tomcat版本不同可能会导致文件太大的异常无法捕获,这里用tomcat6.0.37是没有问题的 -->
<bean id="exceptionResolver"
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 统一处理错误-->
<property name="defaultErrorView" value="error"></property>
<!-- 传递到错误处理页面的错误代码 -->
<property name="exceptionAttribute" value="myException"></property>
<!-- 也可以单独处理 -->
<!--遇到MaxUploadSizeExceededException异常时,自动跳转到ErrFileupload.jsp页面
<propertyname="exceptionMappings">
<props>
<prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">ErrFileupload</prop>
</props>
</property>
-->
</bean>
<!-- 文件上传的参数配置,文件上传的实际操作是由spring自带拦截器完成的 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<!-- 最大值10Mb -->
<property name="maxUploadSize" value="10240000"></property>
</bean>
<bean id="uploadControl" class="com.stu.controls.UploadControl"></bean>
<bean id="downloadControl" class="com.stu.controls.DownloadControl"></bean>
</beans>
====================================================================
知识讲解:【bean id="exceptionResolver"】:是异常解析器,能够统一定位处理程序中抛出的异常。
【<property name="defaultErrorView" value="error"></property>】这句话是定义默认的错误处理页面为error.jsp。
【<property name="exceptionAttribute" value="myException"></property>
】这个配置的作用是把错误代码传递到错误处理页面,例如异常代码是MaxUploadSizeExceededException,那么这个配置相当于调用了request.setAttribute("myException",
"MaxUploadSizeExceededException");
【<bean id="multipartResolver"】表示文件表单解析器,设置文件上传的参数,如最大值和编码。
步骤七:在webroot目录下建立error.jsp
================================error.jsp=======================
<%@ page language="java" import="java.util.*"pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%
String path =request.getContextPath();
String basePath =request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>错误提示</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<c:choose>
<c:when test="${fn:contains(requestScope.myException,'MaxUploadSizeExceededException')}">
<script type="text/javascript">
window.alert("文件太大了");
window.location="index.jsp";
</script>
</c:when>
<c:when test="${fn:contains(requestScope.myException,'FileNotFoundException')}">
<script type="text/javascript">
window.alert("请求的文件未找到");
window.location="index.jsp";
</script>
</c:when>
<c:otherwise>
<script type="text/javascript">
window.alert("发生了其它错误");
window.location="index.jsp";
</script>
</c:otherwise>
</c:choose>
</head>
<body>
</body>
</html>
==================================================================
步骤八:建立DownloadControl.java,如下所示:
=========================DownloadControl.java=====================
public class DownloadControlimplements Controller{
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception{
String fileName=request.getParameter("fileName");
//对a标签提交的文件名乱码处理
fileName=new String(fileName.getBytes("iso-8859-1"),"utf-8");
System.out.println("theName:"+fileName);
HttpSession session=request.getSession();
String filePath=session.getServletContext().getRealPath("/uploads")+"\\";
FileInputStream fis=new FileInputStream(filePath+fileName);
response.setContentType("application/x-msdownload");//表示以下载的方式回复客户请求
fileName=URLEncoder.encode(fileName, "utf-8"); //处理客户端附件的乱码问题
//设置是以附件的形式下载
response.setHeader("Content-Disposition", "attachment;filename="+fileName);
//获得输出流,该输出流表示对客户端请求的反馈
ServletOutputStream sos=response.getOutputStream();
//拷贝输入流到输出流
FileCopyUtils.copy(fis, sos);
sos.close();
fis.close();
return null;
}
}
=====================================================================
步骤十: 启动tomcat,发布项目,在地址栏分别输入 http://localhost:8080/mvcfile
进行测试。 如图所示: