java中struts2实现文件上传下载功能实例解析
本文实例讲述了java中struts2实现文件上传下载功能实现方法。分享给大家供大家参考。具体分析如下:
1.文件上传
首先是jsp页面的代码
在jsp页面中定义一个上传标签
<td align="right" bgcolor="#f5f8f9"><b>附件:</b></td>
<td bgcolor="#ffffff">
<input type="file" name="upload" />
</td>
<td bgcolor="#ffffff"> </td>
</tr>
然后是baseaction中定义的相关属性其它的就省略了(也可定义在自己的action,换下访问修饰符即可)
*action基类
**/
public class baseaction extends actionsupport {
protected list<file> upload;
protected list<string> uploadcontenttype; //文件类型
protected list<string> uploadfilename; //文件名
protected string savepath; //保存路径
}
然后是action中的一个上传方法,代码如下:
* 8.上传附件
* @param upload
*/
public void uploadaccess(list<file> upload){
try {
if (null != upload) {
for (int i = 0; i < upload.size(); i++) {
string path = getsavepath() + ""+ getuploadfilename().get(i);
system.out.println(path);
item.setaccessory(getuploadfilename().get(i));
fileoutputstream fos = new fileoutputstream(path);
fileinputstream fis = new fileinputstream(getupload().get(i));
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fis.close();
fos.close();
}
}
} catch (exception e) {
logger.error("上传附件错误。", e);
}
}
接着是我的struts2.xml文件
<param name="savepath">e:upload</param>
<interceptor-ref name="defaultstack">
<param name="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>
<param name="fileupload.maximumsize">8000000</param>
</interceptor-ref>
<result name="show_item_rd_upd"> /web-inf/jsp/page_item/upditem_rd.jsp</result>
<result name="show_item_rd_list"> /web-inf/jsp/page_item/listitem_rd.jsp</result>
<result name="show_item_rd_push"> /web-inf/jsp/page_item/pushitem_rd.jsp</result>
</action>
savepath为保存路径,fileupload.allowedtypes 用来限制上传文件类型 fileupload.maximumsize 文件大小限制
2.文件下载
首先是页面中的下载链接
<td width="20%" align="right" bgcolor="#f5f8f9"><b>附件:</b></td>
<td width="40%" bgcolor="#ffffff">
<div style="width:355px; float: left;">${item.accessory}</div>
<c:if test="${!empty item.accessory}">
<div class="btn_img" style="float: left;"><a style="color: black; text-decoration: none;" href="download.action?filename=${item.accessory}">下载</a></div>
</c:if>
</td>
<td width="40%" bgcolor="#ffffff"> </td>
</tr>
接着是downloadaction的代码:
* downloadaction
*
* @author zhaoxz
*
*/
@controller("downloadaction")
@scope("prototype")
public class downloadaction extends baseaction {
/**
*
*/
private static final long serialversionuid = -4278687717124480968l;
private static logger logger = logger.getlogger(downloadaction.class);
private string filename;
private inputstream inputstream;
private string savepath;
private string mimetype;
public inputstream getinputstream() {
try {
string path = getsavepath() + "//"+ new string(filename.getbytes("iso8859-1"), "utf-8");
system.out.println(path);
mimetype = servletactioncontext.getservletcontext().getmimetype(path)+ ";charset=utf-8";
inputstream = new fileinputstream(path);
string agent = 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 = new string(filename.getbytes("iso8859-1"),"utf-8");
filename = java.net.urlencoder.encode(filename, "utf-8");
}
}
} catch (exception e) {
logger.error("下载文件信息出错。", e);
}
if (null == inputstream) {
system.out.println("getresource error");
}
return inputstream;
}
public void setinputstream(inputstream inputstream) {
this.inputstream = inputstream;
}
@override
public string execute() throws exception {
return success;
}
/*************************** get set ******************************/
public string getsavepath() {
return this.savepath;
}
public void setsavepath(string savepath) {
this.savepath = savepath;
}
public string getfilename() {
return filename;
}
public void setfilename(string filename) {
this.filename = filename;
}
}
然后是它的struts2.xml文件:
<param name="savepath">e:/upload</param>
<result type="stream">
<param name="contenttype">${mimetype}</param>
<param name="contentdisposition">attachment;filename="${filename}"</param>
<param name="inputname">inputstream</param>
</result>
</action>
下载的话注意下编码格式基本应该就没什么问题了.
上传过程碰到的问题
1.上传大文件就出错解决方法1
出现的错误有如下:
1、2012-02-24 11:06:31,937 error (org.apache.struts2.dispatcher.dispatcher:512) - could not find action or result
no result defined for action com.iman.portal.action.questionactionimpl and result problempage - action - file:/e:/myeclipse/workspaces/portal/webroot/web-inf/classes/struts2/struts-question.xml:51:55
2、the request was rejected because its size (2973652) exceeds the configured maximum (2097152)
中文意思: 要求被拒绝,因为它的大小(2973652)超过配置的最大值(2097152)、
考虑到用户体验,所以必须在上传附件时,拦截这样的异常,解决方法如下:
1、所上传的文件,在上传过程中都是先存放在缓存中的,安全起见,还是在项目的struts.properties文件中,加一个临时存放路径,虽然项目中己经设置好服务器的物理路径。
2、考虑到后期可能会修改文件上传的大小,所以不管是否默认,还是在项目的struts.properties文件中,加如下配置:
<constant name="struts.multipart.maxsize" value="2097152"/>
3、struts.xml配置
<action name="updateproblem" method="updateproblem">
<interceptor-ref name="fileupload"/>
<interceptor-ref name="defaultstack" />
<result name="input">/page/question/page/problempage.jsp</result>
</action>
4、最重要也是最关键的一步
fileupload拦截器只是当文件上传到服务器上之后,才进行的文件类型和大小判断。在action中如果我们什么操作都不做的话,异常就会展现在用户的面前,因此想了一个方法,把该异常信息设置为action级别的错误信息。即重写addactionerror方法。
public void addactionerror(string anerrormessage) {
// 这里要先判断一下,是我们要替换的错误,才处理
if (anerrormessage.startswith("the request was rejected because its size")) {
pattern pattern = pattern.compile("d+");
matcher m = pattern.matcher(anerrormessage);
// 匹配一次
m.find();
string s1 =m.group();//上传的文件大小
// 再匹配一次
m.find();
string s2 =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验证:
var message="${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里面会有如下的提示:
the request was rejected because its size (16272982) exceeds the configured maximum (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之间时,系统提示:
file too large: file "msf的概念.ppt" "upload__5133e516_129ce85285f__7ffa_00000005.tmp" 6007104
当上传的文件小于maximumsize,上传成功。
<result name="uploadfileresult">/pages/showotherfiles.jsp</result>
<result name="jgbsuccess">/pages/jgbdetail.jsp</result>
<interceptor-ref name="fileupload">
<param name="savepath">/data</param>
<param name="maximumsize">52428800</param>
</interceptor-ref>
<interceptor-ref name="defaultstack"></interceptor-ref>
</action>
上传大文件就出错解决办法2:
问题:上传大文件报错……
解决:修改struts.xml文件中的参数如下
<action name="uploadfile" class="com.buptisc.srpms.action.uploadfileaction">
<result name="uploadfileresult">/www.jb51.net/ showotherfiles.jsp</result>
<result name="jgbsuccess">/pages/jgbdetail.jsp</result>
<interceptor-ref name="fileupload">
<param name="savepath">/data</param>
<param name="maximumsize">52428800</param>
</interceptor-ref>
<interceptor-ref name="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里面会有如下的提示:
the request was rejected because its size (16272982) exceeds the configured maximum (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之间时,系统提示:
file too large: file "msf的概念.ppt" "upload__5133e516_129ce85285f__7ffa_00000005.tmp" 6007104
当上传的文件小于maximumsize,上传成功。
上传文件的类型限制
配置fileupload拦截器
struts2的defaultstack中已经含有fileupload拦截器,如果想加入allowedtypes参数,需要从新写一个defaultstack ,拷贝过来修改一下即可:
<interceptor-stack name="mydefaultstack">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="servletconfig"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name=www.jb51.net/>
<interceptor-ref name="chain"/>
<interceptor-ref name="debugging"/>
<interceptor-ref name="profiling"/>
<interceptor-ref name="scopedmodeldriven"/>
<interceptor-ref name="modeldriven"/>
<interceptor-ref name="fileupload">
<param name="allowedtypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="staticparams"/>
<interceptor-ref name="actionmappingparams"/>
<interceptor-ref name="params">
<param name="excludeparams">dojo..*,^struts..*</param>
</interceptor-ref>
<interceptor-ref name="conversionerror"/>
<interceptor-ref name="validation">
<param name="excludemethods">input,back,cancel,browse</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludemethods">input,back,cancel,browse</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="mydefaultstack"></default-interceptor-ref>
仅修改代码中的
<param name="allowedtypes">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
拦截器栈在<package>标签内 <action>标签外配置 如上我们如果把它定义成默认拦截器的话就不需要在
<action>标签中引入,没有的话需要引入拦截器
<result name="input">/error/dberror.jsp</result>
<interceptor-ref name="mydefaultstack"></interceptor-ref>
</action>
文件上传类型错误action会直接返回input,所以不需要在action中return "input" ;
还可以在<package>标签外定义上传问价你的路径跟大小:
<constant name="struts.multipart.maxsize" value="1024"></constant>
最最最重要的一点:上传文件的表单 必须加上:enctype="multipart/form-data" 不加必然报input错误。
希望本文所述对大家的java程序设计有所帮助。