本文实例讲述了java中struts2实现文件上传下载功能实现方法。分享给大家供大家参考。具体分析如下:
1.文件上传
首先是jsp页面的代码
在jsp页面中定义一个上传标签
<tr>
<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文件
<action name=\"itemRDAction_*\" class=\"itemRDAction\" method=\"{1}\">
<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.文件下载
首先是页面中的下载链接
<tr>
<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文件:
<action name=\"download\" class=\"downloadAction\">
<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文件中,加一个临时存放路径,虽然项目中己经设置好服务器的物理路径。
struts.multipart.saveDir=/temp
2、考虑到后期可能会修改文件上传的大小,所以不管是否默认,还是在项目的struts.properties文件中,加如下配置:
<!-- 所允许上传文件的大小2M -->
<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方法。
@Override
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,上传成功。
<action name=\"UploadFile\" class=\"com.buptisc.srpms.action.UploadFileAction\">
<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文件中的参数如下
<constant name=\"struts.multipart.maxSize\" value=\"55000000\"/>
<action name=\"UploadFile\" class=\"com.buptisc.srpms.action.UploadFileAction\">
<result name=\"UploadFileResult\">/www.phpstudy.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 ,拷贝过来修改一下即可:
<interceptors>
<interceptor-stack name=\"myDefaultStack\">
<interceptor-ref name=\"exception\"/>
<interceptor-ref name=\"alias\"/>
<interceptor-ref name=\"servletConfig\"/>
<interceptor-ref name=\"i18n\"/>
<interceptor-ref name=www.phpstudy.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>
仅修改代码中的
<interceptor-ref name=\"fileUpload\">
<param name=\"allowedTypes\">
image/png,image/gif,image/jpeg
</param>
</interceptor-ref>
拦截器栈在<package>标签内 <action>标签外配置 如上我们如果把它定义成默认拦截器的话就不需要在
<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.saveDir\" value=\"/upload/detailed\"></constant>
<constant name=\"struts.multipart.maxSize\" value=\"1024\"></constant>
最最最重要的一点:
上传文件的表单 必须加上:enctype=\"multipart/form-data\" 不加必然报input错误。
希望本文所述对大家的Java程序设计有所帮助。