java中struts2实现文件上传下载功能实例解析
本文实例讲述了java中struts2实现文件上传下载功能实现方法。分享给大家供大家参考。具体分析如下:
1.文件上传
首先是jsp页面的代码
在jsp页面中定义一个上传标签
<tr>
<tdalign="right"bgcolor="#F5F8F9"><b>附件:</b></td>
<tdbgcolor="#FFFFFF">
<inputtype="file"name="upload"/>
</td>
<tdbgcolor="#FFFFFF"> </td>
</tr>然后是BaseAction中定义的相关属性其它的就省略了(也可定义在自己的Action,换下访问修饰符即可)
/**
*Action基类
**/
publicclassBaseActionextendsActionSupport{
protectedList<File>upload;
protectedList<String>uploadContentType;//文件类型
protectedList<String>uploadFileName; //文件名
protectedStringsavePath; //保存路径
}然后是Action中的一个上传方法,代码如下:
/**
*8.上传附件
*@paramupload
*/
publicvoiduploadAccess(List<File>upload){
try{
if(null!=upload){
for(inti=0;i<upload.size();i++){
Stringpath=getSavePath()+""+getUploadFileName().get(i);
System.out.println(path);
item.setAccessory(getUploadFileName().get(i));
FileOutputStreamfos=newFileOutputStream(path);
FileInputStreamfis=newFileInputStream(getUpload().get(i));
byte[]buffer=newbyte[1024];
intlen=0;
while((len=fis.read(buffer))>0){
fos.write(buffer,0,len);
}
fis.close();
fos.close();
}
}
}catch(Exceptione){
logger.error("上传附件错误。",e);
}
}接着是我的struts2.xml文件
<actionname="itemRDAction_*"class="itemRDAction"method="{1}">
<paramname="savePath">e:upload</param>
<interceptor-refname="defaultStack">
<paramname="fileUpload.allowedTypes">
application/octet-stream,image/pjpeg,image/bmp,image/jpg,image/png,image/gif,image/jpeg,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel
</param>
<paramname="fileUpload.maximumSize">8000000</param>
</interceptor-ref>
<resultname="show_item_rd_upd"> /WEB-INF/jsp/page_item/updItem_rd.jsp</result>
<resultname="show_item_rd_list">/WEB-INF/jsp/page_item/listItem_rd.jsp</result>
<resultname="show_item_rd_push">/WEB-INF/jsp/page_item/pushItem_rd.jsp</result>
</action>savePath为保存路径,fileUpload.allowedTypes用来限制上传文件类型fileUpload.maximumSize文件大小限制
2.文件下载
首先是页面中的下载链接
<tr>
<tdwidth="20%"align="right"bgcolor="#F5F8F9"><b>附件:</b></td>
<tdwidth="40%"bgcolor="#FFFFFF">
<divstyle="width:355px;float:left;">${item.accessory}</div>
<c:iftest="${!emptyitem.accessory}">
<divclass="btn_img"style="float:left;"><astyle="color:black;text-decoration:none;"href="download.action?filename=${item.accessory}">下载</a></div>
</c:if>
</td>
<tdwidth="40%"bgcolor="#FFFFFF"> </td>
</tr>接着是DownloadAction的代码:
/**
*DownloadAction
*
*@authorzhaoxz
*
*/
@Controller("downloadAction")
@Scope("prototype")
publicclassDownloadActionextendsBaseAction{
/**
*
*/
privatestaticfinallongserialVersionUID=-4278687717124480968L;
privatestaticLoggerlogger=Logger.getLogger(DownloadAction.class);
privateStringfilename;
privateInputStreaminputStream;
privateStringsavePath;
privateStringmimeType;
publicInputStreamgetInputStream(){
try{
Stringpath=getSavePath()+"//"+newString(filename.getBytes("ISO8859-1"),"utf-8");
System.out.println(path);
mimeType=ServletActionContext.getServletContext().getMimeType(path)+";charset=UTF-8";
inputStream=newFileInputStream(path);
Stringagent=request.getHeader("USER-AGENT");
System.out.println(agent);
if(null!=agent){
if(-1!=agent.indexOf("Firefox")){//Firefox
mimeType=mimeType.replace("UTF-8","ISO8859-1");
}else{//IE7+Chrome
System.out.println("IE,Chrome");
filename=newString(filename.getBytes("ISO8859-1"),"utf-8");
filename=java.net.URLEncoder.encode(filename,"UTF-8");
}
}
}catch(Exceptione){
logger.error("下载文件信息出错。",e);
}
if(null==inputStream){
System.out.println("getResourceerror");
}
returninputStream;
}
publicvoidsetInputStream(InputStreaminputStream){
this.inputStream=inputStream;
}
@Override
publicStringexecute()throwsException{
returnSUCCESS;
}
/***************************getset******************************/
publicStringgetSavePath(){
returnthis.savePath;
}
publicvoidsetSavePath(StringsavePath){
this.savePath=savePath;
}
publicStringgetFilename(){
returnfilename;
}
publicvoidsetFilename(Stringfilename){
this.filename=filename;
}
}然后是它的struts2.xml文件:
<actionname="download"class="downloadAction">
<paramname="savePath">E:/upload</param>
<resulttype="stream">
<paramname="contentType">${mimeType}</param>
<paramname="contentDisposition">attachment;filename="${filename}"</param>
<paramname="inputName">inputStream</param>
</result>
</action>下载的话注意下编码格式基本应该就没什么问题了.
上传过程碰到的问题
1.上传大文件就出错解决方法1
出现的错误有如下:
1、2012-02-2411:06:31,937ERROR(org.apache.struts2.dispatcher.Dispatcher:512)-Couldnotfindactionorresult
Noresultdefinedforactioncom.iman.portal.action.QuestionActionImplandresultproblemPage-action-file:/E:/myeclipse/workspaces/portal/WebRoot/WEB-INF/classes/struts2/struts-question.xml:51:55
2、therequestwasrejectedbecauseitssize(2973652)exceedstheconfiguredmaximum(2097152)
中文意思:要求被拒绝,因为它的大小(2973652)超过配置的最大值(2097152)、
考虑到用户体验,所以必须在上传附件时,拦截这样的异常,解决方法如下:
1、所上传的文件,在上传过程中都是先存放在缓存中的,安全起见,还是在项目的struts.properties文件中,加一个临时存放路径,虽然项目中己经设置好服务器的物理路径。
struts.multipart.saveDir=/temp
2、考虑到后期可能会修改文件上传的大小,所以不管是否默认,还是在项目的struts.properties文件中,加如下配置:
<!--所允许上传文件的大小2M--> <constantname="struts.multipart.maxSize"value="2097152"/>
3、struts.xml配置
<!--修改问题方法-->
<actionname="updateProblem"method="updateProblem">
<interceptor-refname="fileUpload"/>
<interceptor-refname="defaultStack"/>
<resultname="input">/page/question/page/problemPage.jsp</result>
</action>4、最重要也是最关键的一步
fileUpload拦截器只是当文件上传到服务器上之后,才进行的文件类型和大小判断。在Action中如果我们什么操作都不做的话,异常就会展现在用户的面前,因此想了一个方法,把该异常信息设置为Action级别的错误信息。即重写addActionError方法。
@Override
publicvoidaddActionError(StringanErrorMessage){
//这里要先判断一下,是我们要替换的错误,才处理
if(anErrorMessage.startsWith("therequestwasrejectedbecauseitssize")){
Patternpattern=Pattern.compile("d+");
Matcherm=pattern.matcher(anErrorMessage);
//匹配一次
m.find();
Strings1=m.group();//上传的文件大小
//再匹配一次
m.find();
Strings2=m.group();//所限制的大小
if(!s1.equals("")&&!s2.equals("")){
fileUploadErrorMessage="你上传的文件大小("+ Long.valueOf(s1)/1024+"字节)超过允许的大小("+Long.valueOf(s2)/1024/1024+"M)";
getRequest().setAttribute("fileUploadErrorMessage","文件太大,超过了允许的大小("+Long.valueOf(s2)/1024/1024+"M),上传失败!");
//将信息替换掉
super.addActionError(fileUploadErrorMessage);
}
}else{//否则按原来的方法处理
super.addActionError(anErrorMessage);
}
}可以,在返回页面用<s:fielderror/><s:fielderror/>,得到addActionError中的错误内容。
因为我不打算,在页面上显示出来错误原因,想弹出一个提示框,所以将信息放入了request对象中。
而页面加载时,加了如下js验证:
//判断文件是否上传成功
varmessage="${request.fileUploadErrorMessage}";
if(message!=null&&""!=trim(message)&&message!="null"){
self.parent.diag.close();
alert(message);
return;
}下面是一些参考了解东东:
struts.multipart.maxSize掌控整个项目所上传文件的最大的Size
struts.multipart.maxSize和fileUpload拦截器的maximumSize属性分工不同,总结如下:
1.struts.multipart.maxSize掌控整个项目所上传文件的最大的Size。
超过了这个size,后台报错,程序处理不了如此大的文件。fielderror里面会有如下的提示:
therequestwasrejectedbecauseitssize(16272982)exceedstheconfiguredmaximum(9000000)
2.fileUpload拦截器的maximumSize属性必须小于struts.multipart.maxSize的值。
struts.multipart.maxSize默认2M,当maximumSize大于2M时,必须设置struts.multipart.maxSize的值大于maximumSize。
3.当上传的文件大于struts.multipart.maxSize时,系统报错
当上传的文件在struts.multipart.maxSize和maximumSize之间时,系统提示:
Filetoolarge:file"MSF的概念.ppt""upload__5133e516_129ce85285f__7ffa_00000005.tmp"6007104
当上传的文件小于maximumSize,上传成功。
<actionname="UploadFile"class="com.buptisc.srpms.action.UploadFileAction">
<resultname="UploadFileResult">/pages/ShowOtherFiles.jsp</result>
<resultname="JGBsuccess">/pages/JGBdetail.jsp</result>
<interceptor-refname="fileUpload">
<paramname="savePath">/data</param>
<paramname="maximumSize">52428800</param>
</interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>上传大文件就出错解决办法2:
问题:上传大文件报错……
解决:修改struts.xml文件中的参数如下
<constantname="struts.multipart.maxSize"value="55000000"/>
<actionname="UploadFile"class="com.buptisc.srpms.action.UploadFileAction">
<resultname="UploadFileResult">/www.nhooo.com/ShowOtherFiles.jsp</result>
<resultname="JGBsuccess">/pages/JGBdetail.jsp</result>
<interceptor-refname="fileUpload">
<paramname="savePath">/data</param>
<paramname="maximumSize">52428800</param>
</interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>struts.xml文件中的大小与实际文件大小的关系:1048576(Bytes)=1024*1024=1M实际文件大小.
struts.multipart.maxSize掌控整个项目所上传文件的最大的Size
struts.multipart.maxSize和fileUpload拦截器的maximumSize属性分工不同,总结如下:
1.struts.multipart.maxSize掌控整个项目所上传文件的最大的Size。超过了这个size,后台报错,程序处理不了如此大的文件。fielderror里面会有如下的提示:
therequestwasrejectedbecauseitssize(16272982)exceedstheconfiguredmaximum(9000000)
2.fileUpload拦截器的maximumSize属性必须小于struts.multipart.maxSize的值。
struts.multipart.maxSize默认2M,当maximumSize大于2M时,必须设置struts.multipart.maxSize的值大于maximumSize。
3.当上传的文件大于struts.multipart.maxSize时,系统报错
当上传的文件在struts.multipart.maxSize和maximumSize之间时,系统提示:
Filetoolarge:file"MSF的概念.ppt""upload__5133e516_129ce85285f__7ffa_00000005.tmp"6007104
当上传的文件小于maximumSize,上传成功。
上传文件的类型限制
配置fileupload拦截器
struts2的defaultStack中已经含有fileupload拦截器,如果想加入allowedTypes参数,需要从新写一个defaultstack,拷贝过来修改一下即可:
<interceptors>
<interceptor-stackname="myDefaultStack">
<interceptor-refname="exception"/>
<interceptor-refname="alias"/>
<interceptor-refname="servletConfig"/>
<interceptor-refname="i18n"/>
<interceptor-refname=www.nhooo.com/>
<interceptor-refname="chain"/>
<interceptor-refname="debugging"/>
<interceptor-refname="profiling"/>
<interceptor-refname="scopedModelDriven"/>
<interceptor-refname="modelDriven"/>
<interceptor-refname="fileUpload">
<paramname="allowedTypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
<interceptor-refname="checkbox"/>
<interceptor-refname="staticParams"/>
<interceptor-refname="actionMappingParams"/>
<interceptor-refname="params">
<paramname="excludeParams">dojo..*,^struts..*</param>
</interceptor-ref>
<interceptor-refname="conversionError"/>
<interceptor-refname="validation">
<paramname="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-refname="workflow">
<paramname="excludeMethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-refname="myDefaultStack"></default-interceptor-ref>仅修改代码中的
<interceptor-refname="fileUpload">
<paramname="allowedTypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>拦截器栈在<package>标签内<action>标签外配置如上我们如果把它定义成默认拦截器的话就不需要在
<action>标签中引入,没有的话需要引入拦截器
<action>
<resultname="input">/error/dbError.jsp</result>
<interceptor-refname="myDefaultStack"></interceptor-ref>
</action>文件上传类型错误action会直接返回input,所以不需要在action中return"input";
还可以在<package>标签外定义上传问价你的路径跟大小:
<constantname="struts.multipart.saveDir"value="/upload/detailed"></constant> <constantname="struts.multipart.maxSize"value="1024"></constant>
最最最重要的一点:上传文件的表单必须加上:enctype="multipart/form-data"不加必然报input错误。
希望本文所述对大家的Java程序设计有所帮助。