java中Struts2文件上传问题详解
首先是网页部分,upload_file.jsp
<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%> <!DOCTYPEHTML> <html> <head> <title>UploadFile</title> </head> <body> <formaction="UploadFile"method="post"enctype="multipart/form-data"> <!--文件域--> <inputtype="file"name="source"/><inputtype="submit"value="上传"> </form> </body> </html>
上传文件的表单,metho必须设置成post,enctype必须设置成multipart/form-data。
从上面代码中可以看到这个表单提交给了UploadFile这个action来处理,那我们在struts.xml里面配置如下:
<actionname="UploadFile"class="com.lidi.action.UploadAction"> <resultname="success">/uploadResult.jsp</result> <!--fileUpload拦截器,可用于限制上传文档的类型和文档大小--> <interceptor-refname="fileUpload"> <!--限制文件大小20M,单位为字节--> <paramname="maximumSize">20971520</param> </interceptor-ref> <!--默认拦截器,必须声明在fileUpload拦截器之后--> <interceptor-refname="defaultStack"/> </action>
fileUpload拦截器,用于设置上传路径,限制文件类型和大小。
关于限制文件大小,光有<paramname="maximumSize">是不行的,还必须在<struts>标签下添加
<constantname="struts.multipart.maxSize"value="21000000"/>
这行代码表示整个项目所有要上传文件的地方允许上传的文件大小的最大值,也就是说这个项目里上传的任何单个文件大小不能超过21000000字节(约20M),如果项目中不添加这行代码,则默认允许上传的文件大小最大为2M,所以这也是突破struts2只能上传2M文件的限制的方法。
关于限制文件类型,如果需要限制为图片文件,则<interceptor>可以这样配置
<!--设置只允许上传图片文件--> <intercepter-refname="fileUpload"> <paramname="allowedTypes">image/bmp,image/x-png,image/gif,image/jpeg</param> </intercepter-ref> <interceptor-refname="defaultStack"/>
<paramname="allowedTypes">标签中的值都是文件的MIME类型,常用文件的MIME类型可以在%TOMCAT_HOME%\conf\web.xml中找到。
如果要限制为word文件,则可以<interceptor>可以这样配置
<!--设置只允许上传word文档--> <intercepter-refname="fileUpload"> <paramname="allowedTypes">application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document</param> </intercepter-ref> <interceptor-refname="defaultStack"/>
然而我感觉这样来限制文件类型,不如用javascript在前端实现限制。
接下来写UploadAction,UploadAction必需的私有属性是source,这是和upload_file.jsp里面文件域的name属性是一致,就是说文件域的name属性值为source,则UploadAction中必需有私有属性source,另外,还有两个比较重要的私有属性:
privateStringsourceFileName;//待上传文件的文件名
privateStringsourceContentType;//待上传文件的文件类型
这两个变量名的格式就是前面的前缀source和upload_file.jsp中的文件域的name属性相同。
综合来说,就是,比如upload_file.jsp中文件域的name=“abc”,则Action中就需要这样定义
privateFileabc; privateStringabcFileName; privateStringabcContentType;
abc会自动获取要上传的文件对象,abcFileName自动获取文件名,abcContentType自动获取文件类型。
关于上传路径,是我要重点说一下的。
如果是上传到绝对路径,那还挺好搞的,但如果要上传到项目根目录下的upload文件夹呢,怎么获得这个upload文件夹的完整路径?
我尝试过使用
ServletActionContext.getServletContext().getRealPath("/upload");
但返回了null。也用过
ServletActionContext.getRequest().getRealPath("/upload");
还是返回了null。但在网上查下这个问题,很多人都推荐这么写,证明可能某些情况下这样写确实是可行的,但也有跟我一样返回null的人,他们同时推荐了一种新的方法,就是让UploadAction实现ServletContextAware接口。具体做法如下:
publicclassUploadActionextendsActionSupportimplementsServletContextAware{ /** *省略其它代码... */ privateServletContextcontext; publicServletContextgetContext(){ returncontext; } publicvoidsetContext(ServletContextcontext){ this.context=context; } @Override publicvoidsetServletContext(ServletContextcontext){ this.context=context; } }
然后使用
Stringpath=context.getRealPath("/upload");//重要:斜杠不能少
获得upload文件夹的路径。然后执行上传:
/*将文件上传到upload文件夹下*/ Filesavefile=newFile(path,sourceFileName); FileUtils.copyFile(source,savefile);
我个人是比较推荐这种方法的,因为这种方法好像规避了当项目被打包转移到其它环境时也能保证获得正确的路径。
后面贴上UploadAction的完整代码UploadAction.java
packagecom.lidi.action; importjava.io.File; importjava.io.IOException; importjavax.servlet.ServletContext; importorg.apache.commons.io.FileUtils; importorg.apache.struts2.util.ServletContextAware; importcom.opensymphony.xwork2.ActionSupport; publicclassUploadActionextendsActionSupportimplementsServletContextAware{ /** * */ privatestaticfinallongserialVersionUID=1L; privateFilesource;//待上传文件 privateStringsourceFileName;//待上传文件的文件名 privateStringsourceContentType;//待上传文件的文件类型 privateServletContextcontext;//重要 /*重要*/ publicServletContextgetContext(){ returncontext; } publicvoidsetContext(ServletContextcontext){ this.context=context; } /*getters&setters*/ publicFilegetSource(){ returnsource; } publicvoidsetSource(Filesource){ this.source=source; } publicStringgetSourceFileName(){ returnsourceFileName; } publicvoidsetSourceFileName(StringsourceFileName){ this.sourceFileName=sourceFileName; } publicStringgetSourceContentType(){ returnsourceContentType; } publicvoidsetSourceContentType(StringsourceContentType){ this.sourceContentType=sourceContentType; } @Override publicvoidsetServletContext(ServletContextcontext){ this.context=context; } publicStringexecute()throwsIOException{ /*获取存放上传文件的路径:项目根目录upload文件夹*/ Stringpath; path=context.getRealPath("/upload");//重要:斜杠不能少 System.out.println(path); /*将文件上传到upload文件夹下*/ Filesavefile=newFile(path,sourceFileName); FileUtils.copyFile(source,savefile); System.out.println(savefile.getAbsolutePath()); returnSUCCESS; } }
上传结果页uploadResult.jsp
<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%> <%@tagliburi="/struts-tags"prefix="s"%> <!DOCTYPEHTML> <html> <head> <title>UploadResult</title> </head> <body> <p>文件名:<s:propertyvalue="sourceFileName"/></p> <p>文件类型:<s:propertyvalue="sourceContentType"/></p> <p>文件:<ahref="upload/<s:propertyvalue="sourceFileName"/>"><s:propertyvalue="sourceFileName"/></a></p> </body> </html>
以上所述就是本文的全部内容了,希望大家能够喜欢。