java中struts2实现文件上传下载功能实例解析
本篇章节讲解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,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 中文意思: 要求被拒绝,因为它的大小(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 1.struts.multipart.maxSize掌控整个项目所上传文件的最大的Size。 复制代码 代码如下: <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: 问题:上传大文件报错…… 复制代码 代码如下: <constant name="struts.multipart.maxSize" value="55000000"/> <action name="UploadFile" class="com.buptisc.srpms.action.UploadFileAction"> <result name="UploadFileResult">/www.aspzz.cn/ 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里面会有如下的提示: 上传文件的类型限制 配置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.aspzz.cn/> <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/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,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/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程序设计有所帮助。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |