




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Struts的FormFile与Commons- FileUpload控件使用心得前一段时间刚来公司,看到一个项目中以前有人写的struts代码。是使用了FormFile来处理关于文件上传的模块。但是用力一段时间后,发现出问题 了。写完的这个模块,上传文件是没有问题的,但是当服务器的空间较小的时候,穿一个比较大的文件就出问题了,文件还没有上传完,就抛出一个错误的页面,报 告上传模块出了问题,而且是Tomcat默认的出错页面。 于是想办法,修改,查看源代码,发现原来写这段代码的人是默认等文件上传完以后进入Action了才判断文件大小是否超出了限制。 但是,默认配置下使用struts的FormFile比较特殊,FormFile是struts包对外的一个接口,而且 org.apache.struts.upload包是使用的commons-fileupload-1.0进行的封装。如果使用了它来实现文件上传的功 能,则必须是FormFile对象在被初始化以后才能使用,那什么时候它才是被初始化的呢? 答案是:在进入Action之前就已经初始化好了! 因此,原先的设计:在Action中判断文件大小是根本不能在上传过程中起到提示作用的,因为这时候文件已经上传完了。而且这个设计还有一个确定 就是不能捕获上传过程中出现的任何问题。也就是说:在Action里我们得到的FormFile对象是上传的一个结果,而不是一个未上传好就可以使用的对 象! 那如何控制FormFile上传的过程呢?显然,在Action里处理已经不能奏效了,想想别的办法,让我们翻看一下Struts的源代码找找灵感吧。 这是struts1.1的org.apache.struts.upload包的描述: (见附件) 从上图我们可以看出有有CommonsMultipartRequestHandler和DiskMultipartRequestHandler两个类 实现了MultipartRequestHandler接口。 大家都知道,Commons-fileupload控件在上传的时候,使用的enctype 为:enctype=multipart/form-data,因此不难看出MultipartRequestHandler的实 现就是来处理enctype=multipart/form-data这样的post请求的。 但是这里有两个类,CommonsMultipartRequestHandler和DiskMultipartRequestHandler。到底哪个 是处理FormFile的上传的呢?这个问题应该从org.apache.struts.config包里来找。 org.apache.struts.config包是用来处理struts配置文件的数据的包。找到 org.apache.struts.config. ControllerConfig。 看这几行: Java 代码 1. /*2. *ThefullyqualifiedJavaclassnameoftheMultipartRequestHandler3. *classtobeused.4. */5. protectedStringmultipartClass=6. org.apache.struts.upload.CommonsMultipartRequestHandler;7. 8. publicStringgetMultipartClass()9. 10. return(this.multipartClass);11. 12. 13. publicvoidsetMultipartClass(StringmultipartClass)14. 15. if(configured)16. 17. thrownewIllegalStateException(Configurationisfrozen);18. 19. 20. this.multipartClass=multipartClass;21. /* * The fully qualified Java class name of the MultipartRequestHandler * class to be used. */ protected String multipartClass = org.apache.struts.upload.CommonsMultipartRequestHandler; public String getMultipartClass() return (this.multipartClass); public void setMultipartClass(String multipartClass) if (configured) throw new IllegalStateException(Configuration is frozen); this.multipartClass = multipartClass; 这几行的意思很明白,如果没有在配置文件中配置MultipartRequestHandler实现类的绝对路径,那就使用 org.apache.struts.upload.CommonsMultipartRequestHandler类默认处理。 _,这就是关键了:struts是默认使用 org.apache.struts.upload.CommonsMultipartRequestHandler类来处理FormFile指定的上传 文件的。 马上转到org.apache.struts.upload.CommonsMultipartRequestHandler来看看: Java 代码 1. /*2. *默认文件上传的大小是250M3. */4. publicstaticfinallongDEFAULT_SIZE_MAX=250*1024*1024;5. /*6. *上传文件在内存中使用的缓冲区大小,超过次数值的数据写入硬盘。7. */8. publicstaticfinalintDEFAULT_SIZE_THRESHOLD=256*1024;/* *默认文件上传的大小是250M */ public static final long DEFAULT_SIZE_MAX = 250 * 1024 * 1024; /* *上传文件在内存中使用的缓冲区大小,超过次数值的数据写入硬盘。 */ public static final int DEFAULT_SIZE_THRESHOLD = 256 * 1024; 还有,最最重要的实现方法: Java 代码 1. /*2. *Parsestheinputstreamandpartitionstheparseditemsintoasetof3. *formfieldsandasetoffileitems.Intheprocess,theparseditems4. *aretranslatedfromCommonsFileUploadFileIteminstances5. *toStrutsFormFileinstances.6. *paramrequestThemultipartrequesttobeprocessed.7. *throwsServletExceptionifanunrecoverableerroroccurs.8. 就是这个函数处理上传文件的request,把request交给CommonsFileUpload控件处理, 并解析FileItem转换成Struts的FormFile。9. */10. publicvoidhandleRequest(HttpServletRequestrequest)throwsServletException/* * Parses the input stream and partitions the parsed items into a set of * form fields and a set of file items. In the process, the parsed items * are translated from Commons FileUpload FileItem instances * to Struts FormFile instances. * param request The multipart request to be processed. * throws ServletException if an unrecoverable error occurs. 就是这个函数处理上传文件的request,把request交给Commons FileUpload 控件处理,并解析FileItem转换成Struts的FormFile。 */public void handleRequest(HttpServletRequest request) throws ServletException 再看看这个函数内部是怎么实现的吧? Java 代码 1. /使用了DiskFileUpload。2. /(Commons-FileUpload很老版本的一个上传实现类了,还在用?我的显示是 Deprecated)3. DiskFileUploadupload=newDiskFileUpload();4. /上传最大值5. upload.setSizeMax(int)getSizeMax(ac);6. /上传文件在内存中使用的缓冲区大小7. upload.setSizeThreshold(int)getSizeThreshold(ac);8. /存在硬盘的什么地方,一般是默认9. pload.setRepositoryPath(getRepositoryPath(ac);/ 使用了DiskFileUpload。 / (Commons-FileUpload很老版本的一个上传实现类了,还在用?我的显示是Deprecated) DiskFileUpload upload = new DiskFileUpload(); / 上传最大值 upload.setSizeMax(int) getSizeMax(ac); / 上传文件在内存中使用的缓冲区大小 upload.setSizeThreshold(int) getSizeThreshold(ac); / 存在硬盘的什么地方,一般是默认pload.setRepositoryPath(getRepositoryPath(ac); 接着看handleRequest如何处理request的: Java 代码 1. /Parsetherequestintofileitems.2. Listitems=null;3. try4. 5. items=upload.parseRequest(request);6. 7. /这里是关键:上传过程中出了超出最大值的异常了,如何处理?8. catch(DiskFileUpload.SizeLimitExceededExceptione)9. 10. /Specialhandlingforuploadsthataretoobig11. request.setAttribute(12. MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED,13. Boolean.TRUE);14. return;15. 16. /出了其他异常,如enctype不对,磁盘空间不足怎么办?17. catch(FileUploadExceptione)18. 19. log.error(Failedtoparsemultipartrequest,e);20. thrownewServletException(e);21. / Parse the request into file items. List items = null; try items = upload.parseRequest(request); /这里是关键:上传过程中出了超出最大值的异常了,如何处理? catch (DiskFileUpload.SizeLimitExceededException e) / Special handling for uploads that are too big request.setAttribute(MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED, Boolean.TRUE); return; /出了其他异常,如enctype不对,磁盘空间不足怎么办? catch (FileUploadException e) log.error(Failed to parse multipart request, e); throw new ServletException(e); 这次一目了然了: Struts根本没有把上传过程中出的超出最大值的异常带到Action,而是把它放到了rquest的 Attribute里。 而出了其他异常如enctype不对,磁盘空间不足怎么办?很遗憾,Struts没有去处理它,而是log了一下,抛给了 上一层了。 那我一定要获得这些全部异常咋办呢?没办法,自己定制一个MultipartRequestHandler吧,那样就能彻 底解决上传过程中的控制问题了! 在此之前,我们得先去最新版的commons-fileupload控件看看上传过程中可能抛出多少异常? Java 代码 1. 2. /所有上传异常的父类3. mons.fileupload.FileUploadException4. /注意:这个类的类名是FileUploadBase.SizeLimitExceededException是个 public内5. / 部类。上传的formdata总的数据超出了规定大小6. mons.fileupload.FileUploadBase.SizeLimitExceededException7. /注意:也是个内部类。这个才是上传的文件超出了规定大小8. mons.fileupload.FileUploadBase.FileSizeLimitExceededException9. /其它的,也看看吧:10. mons.fileupload.FileUploadBase.FileUploadIOException11. mons.fileupload.FileUploadBase.InvalidContentTypeException12. mons.fileupload.FileUploadBase.IOFileUploadException13. mons.fileupload.FileUploadBase.UnknownSizeException /所有上传异常的父类mons.fileupload.FileUploadException /注意:这个类的类名是FileUploadBase.SizeLimitExceededException是个public内/部类。上传的formdata总的数据超出了规定大小mons.fileupload.FileUploadBase.SizeLimitExceededException /注意:也是个内部类。这个才是上传的文件超出了规定大小mons.fileupload.FileUploadBase.FileSizeLimitExceededException/其它的,也看看吧:mons.fileupload.FileUploadBase.FileUploadIOEmons.fileupload.FileUploadBase.InvalidContentTypeEmons.fileupload.FileUploadBase.IOFileUploadEmons.fileupload.FileUploadBase.UnknownSizeException 要想获得尽可能仔细的数据就在处理的try/catch块里把上面的异常都catch一下,放到request的attribute里去就OK了。 另外还有要说的是,最好用commons-fileupload控件的最新版本,因为DiskFileUpload这个 类,commons-fileupload已经弃用了,取而代之的是ServletFileUpload类了,所以一定要注意!切记,切记. 这是我写的CommonsMultipartRequestHandler替代类的public void handleRequest(HttpServletRequest request) throws ServletException函数: Java 代码 1. publicvoidhandleRequest(HttpServletRequestrequest)throwsServletException2. 3. /Gettheappconfigforthecurrentrequest.4. ModuleConfigac=(ModuleConfig)request.getAttribute(Globals.MODULE_KEY);5. 6. /DiskFileItem工厂,主要用来设定上传文件的参数7. DiskFileItemFactoryfileItemFactory=newDiskFileItemFactory();8. 9. /上传文件所用到的缓冲区大小,超过此缓冲区的部分将被写入到磁盘10. fileItemFactory.setSizeThreshold(int)this.getSizeThreshold(ac);11. 12. /上传文件用到的临时文件存放位置13. fileItemFactory.setRepository(this.getRepository(ac);14. 15. /使用fileItemFactory为参数实例化一个ServletFileUpload对象16. /注意:该对象为commons-fileupload-1.2新增的类.17. /对于1.2以下的commons-fileupload版本并不存在此类.18. ServletFileUploadupload=newServletFileUpload(fileItemFactory);19. 20. /从session中读取对本次上传文件的最大值的限制21. StringmaxUploadSize=(String)request.getSession().22. getAttribute(BasicConstants.maxUploadSize);23. 24. /获取struts-config文件中controller标签的maxFileSize属性来确定默认上传的 限制25. /如 果struts-config文件中controller标签的maxFileSize属性没设置则使用默认的上传限制250M.26. longdefaultOrConfigedMaxUploadSize=this.getSizeMax(ac);27. if(maxUploadSize!=null&maxUploadSize!=)28. 29. /如果maxUploadSize设定不正确则上传限制为 defaultOrConfigedMaxUploadSize的值30. 31. /正确则为maxUploadSize转换成的字节数32. upload.setSizeMax(long)this.convertSizeToBytes(33. maxUploadSize,defaultOrConfigedMaxUploadSize);34. 35. 36. else37. 38. /如果maxUploadSize没设置则使用默认的上传限制39. upload.setSizeMax(defaultOrConfigedMaxUploadSize);40. 41. 42. /从session中清空maxUploadSize43. request.getSession().removeAttribute(maxUploadSize);44. 45. /Createthehashtablestobepopulated.46. elementsText=newHashtable();47. elementsFile=newHashtable();48. elementsAll=newHashtable();49. 50. /Parsetherequestintofileitems.51. Listitems=null;52. /ServletFileUpload类来处理表单请求53. /抛出的异常为FileUploadException的子异常54. /如果捕获这些异常就将捕获的异常放到session中返回.55. 56. try57. 58. items=upload.parseRequest(request);59. 60. 61. catch(FileUploadBase.SizeLimitExceededExceptione)62. 63. 64. /请求数据的size超出了规定的大小.65. request.getSession().setAttribute(66. BasicConstants.baseSizeLimitExceededException,e);67. return;68. 69. catch(FileUploadBase.FileSizeLimitExceededExceptione)70. 71. /请求文件的size超出了规定的大小.72. request.getSession().setAttribute(73. BasicConstants.baseFileSizeLimitExceededException,e);74. return;75. 76. catch(FileUploadBase.IOFileUploadExceptione)77. 78. /文件传输出现错误,例如磁盘空间不足等.79. request.getSession().setAttribute(80. BasicConstants.baseIOFileUploadException,e);81. return;82. 83. catch(FileUploadBase.InvalidContentTypeExceptione)84. 85. /无效的请求类型,即请求类型enctype!=multipart/form-data86. request.getSession().setAttribute(87. BasicConstants.baseInvalidContentTypeException,e);88. return;89. 90. catch(FileUploadExceptione)91. 92. /如果都不是以上子异常,则抛出此总的异常,出现此异常原因无法说明.93. request.getSession().setAttribute(94. BasicConstants.FileUploadException,e);95. return;96. 97. 98. /Partitiontheitemsintoformfieldsandfiles.99. Iteratoriter=items.iterator();100. 101. while(iter.hasNext()102. 103. FileItemitem=(FileItem)iter.next();104. 105. if(item.isFormField()106. 107. addTextParameter(request,item);108. 109. else110. 111. addFileParameter(item);112. 113. 114. public void handleRequest(HttpServletRequest request) throws ServletException / Get the app config for the current request. ModuleConfig ac = (ModuleConfig) request.getAttribute(Globals.MODULE_KEY); / DiskFileItem工厂,主要用来设定上传文件的参数 DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(); / 上传文件所用到的缓冲区大小,超过此缓冲区的部分将被写入到磁盘 fileItemFactory.setSizeThreshold(int) this.getSizeThreshold(ac); / 上传文件用到的临时文件存放位置 fileItemFactory.setRepository(this.getRepository(ac); / 使用fileItemFactory为参数实例化一个ServletFileUpload对象 / 注意:该对象为commons-fileupload-1.2新增的类. / 对于1.2以下的commons-fileupload版本并不存在此类. ServletFileUpload upload = new ServletFileUpload(fileItemFactory); / 从session中读取对本次上传文件的最大值的限制 String maxUploadSize = (String)request.getSession().getAttribute(BasicConstants.maxUploadSize); / 获取struts-config文件中controller标签的maxFileSize属性来确定默认上传的限制 / 如果struts-config文件中controller标签的maxFileSize属性没设置则使用默认的上传限制250M. long defaultOrConfigedMaxUploadSize = this.getSizeMax(ac); if (maxUploadSize != null & maxUploadSize != ) / 如果maxUploadSize设定不正确则上传限制为defaultOrConfigedMaxUploadSize的值 / 正确则为maxUploadSize转换成的字节数 upload.setSizeMax(long) this.convertSizeToBytes(maxUploadSize, defaultOrConfigedMaxUploadSize); else / 如果maxUploadSize没设置则使用默认的上传限制 upload.setSizeMax(defaultOrConfigedMaxUploadSize); / 从session中清空maxUploadSize request.getSession().removeAttribute(maxUploadSize); / Create the hash tables to be populated. elementsText = new Hashtable(); elementsFile = new Hashtable(); elementsAll = new Hashtable(); / Parse the request into file items. List items = null; / ServletFileUpload类来处理表单请求 / 抛出的异常为FileUploadException的子异常 / 如果捕获这些异常就将捕获的异常放到session中返回. try items = upload.parseRequest(request); catch (FileUploadBase.SizeLimitExceededException e) / 请求数据的size超出了规定的大小. request.getSession().setAttribute( BasicConstants.baseSizeLimitExceededException, e); return; catch (FileUploadBase.FileSizeLimitExceededException e) / 请求文件的size超出了规定的大小. request.getSession().setAttribute( BasicConstants.baseFileSizeLimitExceededException, e); return; catch (FileUploadBase.IOFileUploadException e) / 文件传输出现错误,例如磁盘空间不足等. request.getSession().setAttribute( BasicConstants.baseIOFileUp
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025河南郑州轨道工程职业学院招聘辅导员、教师共75名考前自测高频考点模拟试题及完整答案详解1套
- 2025年冀北博望电力产业管理(北京)有限公司高校毕业生招聘(第三批)模拟试卷附答案详解(突破训练)
- 2025春季中材国际校园招聘163人考前自测高频考点模拟试题有答案详解
- 2025年融资租赁合同特征与范本解析
- 2025湖南岳阳临湘市城东粮食收储有限公司招聘考前自测高频考点模拟试题附答案详解(完整版)
- 初中信息技术考试题库及答案app
- 项目统计考试题库及答案
- 品质工具考试题库及答案
- 泰安高压电工考试题库及答案
- 中专口腔考试题库及答案
- 《水利水电建设工程验收规程》-SL223-2008
- AIOT智能物联产业学院建设方案
- 行政管理专业教学实施细则
- 闭合性颅脑损伤重型个案护理
- 紫金矿业员工工作手册
- FZ-T 01158-2022 纺织品 织物刺痒感的测定 振动音频分析法
- 工程部造价管控手册
- 2024公安联考行测题库
- 民政信访业务培训课件
- 行政检查业务培训课件
- 汽车销售三方协议
评论
0/150
提交评论