在使用了 Struts2 框架的系统中,对于处理像下面这种表单上传文件时:
view source
print?
1.
自然而然的想法就是在 Action 中声明变量 File upload 和 String desc,请求提交到这个 Action 后,在 execute() 方法中就能直接使用 upload 和 desc 了,它们已被 Struts2 框架(org.apache.struts2.interceptor.FileUploadInterceptor 监听器) 赋上了相应的值了。
因为维护的是一个古老的项目,请求都是直接提交给 jsp。在这个项目中套上了 Struts2 已是不易了。原来项目是用的 jspSmartUpload 来处理上传文件的,Struts2 一上 jspSmartUpload 便不能正常工作了,因为 Struts2 的过滤器 org.apache.struts2.dispatcher.FilterDispatcher 拦截的是所有的请求,在交把请求交给 jspSmartUpload 之前请求 request 就已被处理过了,即使是把 struts2-core-2.x.x.jar 中的 struts-default.xml fileUpload 取消了也是如此。
暂时又不想再新加一个 Action,声明 upload:File 和 desc:String 直接接收参数,这样改动的话实在是大,现在 struts.xml 和 struts.properties 文件还是空的呢。所以姑且在原来那个 jsp 中处理吧。
最早做过 jsp 文件上传的人都知道,给 form 加上 enctype="multipart/form-data" 属性后,request.getParameter("desc") 取输入框的值就失灵了,因为页面请求数据是以流的形式发送给服务器的,所以 jspSmartUpload 用了它自己的 Request, com.jspsmart.upload.SmartUpload.getRequest().getParameter("desc") 来接收文本框数据,但对于 Struts2 处理过的 request jspSmartUpload 就无能为力了。
那么在 Struts2 中的 jsp 如何获取到 enctype="multipart/form-data" 表单传递过来的文本输入和文件呢?
·获取文本框的值 ,仍然可用 request.getParameter("desc"),因为此时的 request 是由 org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper 实现的。
对比一下不同时候 request 的具体实现类(Tomcat 环境中)
form enctype multipart/form-data application/x-www-form-urlencoded
Struts2 org.apache.struts2.dispatcher.multipart
.MultiPartRequestWrapper org.apache.struts2.dispatcher
.StrutsRequestWrapper
Struts1 org.apache.struts.upload
.MultipartRequestWrapper org.apache.coyote.tomcat5
.CoyoteRequestFacade
无框架 org.apache.coyote.tomcat5
.CoyoteRequestFacade org.apache.coyote.tomcat5
.CoyoteRequestFacade
·获取上传来的文件 用就要对 request 作个转型,才能调用到相应的方法
view source
print?
1.MultiPartRequestWrapper mpRequest = (MultiPartRequestWrapper)request;
2.
3.File[] files = mpRequest.getFiles("upload"); //文件现在还在临时目录中
4.String[] fileNames = mpRequest.getFileNames("upload");
5.
6.//然后就可以处理你的业务了
其他方法可以查看 MultiPartRequestWrapper API,MultiPartRequestWrapper 是继承自 org.apache.struts2.dispatcher.StrutsRequestWrapper 的。
最后,用了 Struts2 来上传文件,最好在 web.xml 中加上 ActionContextCleanUp 过滤器以避免一些未不预知的异常。
view source
print?
01.
02.
03.
04.
05.
06.
07.
08.
09.
网上有人说是要加 ActionContextCleanUp 过滤器的,ActionContextCleanUp 的代码注释是它易于同 SiteMesh 的整合,至于为何与文件上传扯上关系,我以后也会关注的。
对了还要在项目中引入 commons-fileupload-x.x.x.jar 和 commons-io-x.x.jar 包,其他没有什么特别的配置,默认即可。相信本文的实用性不强,不会有人用 jsp 来处理这些事情,参考价值可能还有一些。