浅谈对struts2.2 the request was rejected because its size (XXXX) exceeds the configured maximum (XXXX)错

最近在学struts2 ,在上传文件时发现有个异常不好处理,经过google终于有点小眉目,现浅谈下这个异常处理。有不妥当的地方还请指教

 http://blog.csdn.net/dxswzj

 

  在struts2中我们上传文件大于struts.multipart.maxSize设置的值时会抛出the request was rejected because its size (XXXX) exceeds the configured maximum (XXXX)异常,他是不能被国际化的,这信息对应用户来说是非常不友好的,那任何处理?

 

在struts2.2 中有两个地方设置上传文件大小:

   一个是在拦截器fileUpload中设置

1000000

   一个是在struts2 自带的文件default.properties中设置的(系统默认大小2M)

   struts.multipart.maxSize=2097152

   这个可以在struts.propertise 文件中修改

 

那这两个有什么区别呢?

   Struts2框架底层默认用的是apache的commons-fileupload组件对上传文件进行接受处理。struts.multipart.maxSize设置的大小就是该处理时取用的值,在上传文件之前系统会去比较文件的大小是否超过了该值,如果超过将抛出上述异常,commons-fileupload组件是不支持国际化的,所以我们看到的异常都是默认的。

   fileUpload拦截器只是当文件上传到服务器上之后,才进行的文件类型和大小判断。 如果上传的文件大小刚好这struts.multipart.maxSize与maximumSize 之间会抛出 key  struts.messages.error.file.too.large 对应的异常信息,这个才支持国际化。那不是把struts.multipart.maxSize设很大,不就解决问题了吗?非也! fileUpload拦截器只是当文件上传到服务器上之后,才进行的文件类型和大小判断,这样会造成系统产生多余没用的文件。

 

那该如何是好?

   其实解决的办法有多种,我这里介绍种最简单的方法:
   在struts2.2 org.apache.commons.fileupload.FileUploadBase.java 中我们看到

  /** * Creates a new instance. * @param ctx The request context. * @throws FileUploadException An error occurred while * parsing the request. * @throws IOException An I/O error occurred. */ FileItemIteratorImpl(RequestContext ctx) throws FileUploadException, IOException { if (ctx == null) { throw new NullPointerException("ctx parameter"); } String contentType = ctx.getContentType(); if ((null == contentType) || (!contentType.toLowerCase().startsWith(MULTIPART))) { throw new InvalidContentTypeException( "the request doesn't contain a " + MULTIPART_FORM_DATA + " or " + MULTIPART_MIXED + " stream, content type header is " + contentType); } InputStream input = ctx.getInputStream(); if (sizeMax >= 0) { int requestSize = ctx.getContentLength(); if (requestSize == -1) { input = new LimitedInputStream(input, sizeMax) { protected void raiseError(long pSizeMax, long pCount) throws IOException { FileUploadException ex = new SizeLimitExceededException( "the request was rejected because" + " its size (" + pCount + ") exceeds the configured maximum" + " (" + pSizeMax + ")", pCount, pSizeMax); throw new FileUploadIOException(ex); } }; } else { ///////////问题就在这里//////////////////////////////////// if (sizeMax >= 0 && requestSize > sizeMax) { throw new SizeLimitExceededException( "the request was rejected because its size (" + requestSize + ") exceeds the configured maximum (" + sizeMax + ")", requestSize, sizeMax); } } } String charEncoding = headerEncoding; if (charEncoding == null) { charEncoding = ctx.getCharacterEncoding(); } boundary = getBoundary(contentType); if (boundary == null) { throw new FileUploadException( "the request was rejected because " + "no multipart boundary was found"); } notifier = new MultipartStream.ProgressNotifier(listener, ctx.getContentLength()); multi = new MultipartStream(input, boundary, notifier); multi.setHeaderEncoding(charEncoding); skipPreamble = true; findNextItem(); }

实际上他是把该异常信息设置为Action级别的错误信息。

了解完这个就好办了,我们可以在action中直接重写ActionSupport的addActionError()方法,

 

/** * 替换文件上传中出现的错误信息 *引用 import java.util.regex.Matcher; * import java.util.regex.Pattern; * * */ @Override public void addActionError(String anErrorMessage) { //这里要先判断一下,是我们要替换的错误,才处理 if (anErrorMessage.startsWith("the request was rejected because its size")) { Matcher m = Pattern.compile("//d+").matcher(anErrorMessage); String s1 = ""; if (m.find()) s1 = m.group(); String s2 = ""; if (m.find()) s2 = m.group(); //偷梁换柱,将信息替换掉 super.addActionError("你上传的文件大小(" + s1 + ")超过允许的大小(" + s2 + ")"); //也可以改为在Field级别的错误 // super.addFieldError("file","你上传的文件大小(" + s1 + ")超过允许的大小(" + s2 + ")"); } else {//否则按原来的方法处理 super.addActionError(anErrorMessage); } }  

这时这页面增加

 

就可以了。

 

做到这里还有个问题,就是原来页面上输入的其他文本内容也都不见了,也就是说params注入失败。

这个是没办法的,因为这个异常是在文件上传之前捕获的,文件未上传,同时params也为注入,所以这时最好重定向到一个jsp文件,提示上传失败,然后重写填写相应信息。

 

 

 

你可能感兴趣的:(SSH)