struts2文件上传松动参数

使用Struts 2.3.15.1

在struts2中实现文件上传。 这是我已经多次做过的事情,但是,我试图包括一些健全性检查(主要是最大文件大小)。 我将fileUpload拦截器作为我的堆栈中的最后一个拦截器(即struts.xml )。 我的堆栈包括一些内部拦截器以及validationWorkflowStack 。 我在struts.properties文件中设置了以下属性:

struts.multipart.maxSize = 2000000 

除了文件上传之外,我还在表单中传递了一些其他参数。 表格定义为:

    ....  

我相信大家都知道, validationWorkflowStack包含了params拦截器,它将请求参数设置为动作。 这是问题,当上传的文件超过maxSize时params拦截器没有设置的参数 。 我已经介入了,而actionContext中没有任何内容。 这不好,因为我需要那些参数来处理将导致的INPUT错误。

我错过了什么吗?

问题解决了 !

从更新的文档中 ,现在可以通过使用新的JakartaStreamMultiPartRequest来解决问题:

从Struts版本2.3.18开始,添加了一个新的MultiPartRequest实现 – JakartaStreamMultiPartRequest。 它可用于处理大文件,有关详细信息,请参阅WW-3025 ,但您可以进行简单设置

  

在struts.xml中开始使用它。

来自链接的JIRA机构:

当任何大小限制超过时,立即抛出FileUploadBase.SizeLimitExceededException或FileUploadBase.FileSizeLimitExceededException,并且多部分请求的解析终止,而不提供进一步处理的请求参数。

这基本上使得任何Web应用程序都无法优雅地处理超出大小限制的情况。

我的建议是,请求解析应始终完成以传递请求参数。 超出大小限制的情况/exception可能被收集以供以后检索,FileSizeLimitExeededException应映射到FileItem以允许在应用程序级别上对FileItem进行一些validation。 如果上传的文件太大,这将允许将上传输入字段标记为错误。

实际上我为此做了补丁(见附件)。 使用此补丁,commons-fileupload总是在大小限制超出的情况下完成请求解析,并且只有在完成解析后才会在检测到exception时抛出exception。

和Chris Cranford的评论:

我正在为Struts2开发一个新的多部分解析器我正在调用JakartaStreamMultiPartRequest。

这个多部分解析器的行为与现有的Jakarta多部分解析器相同,只是它使用Commons FileUpload Streaming API而不是将最大请求大小检查委托给文件上载API,它是在内部完成的,以避免上传API的现有问题打破循环迭代和参数丢失。

太棒了,谢谢你们:)


老答案

我想这是由于不同的行为

  • 超过其最大定义大小的单个文件(或更多文件),然后可以使用INPUT结果在正常过程结束时重定向回来,并且
  • 违反整个Request的最大大小,将(可能?)破坏任何其他元素解析,因为它是一种安全机制,而不是像文件大小检查那样的function;

首先解析文件( 它应该取决于它们在页面中的顺序 ),如果文件突破了多部分请求大小的限制,则不会读取其他字段(表单字段),因此不会返回INPUT结果。

Struts2使用 MultiPartRequestWrapper 的Jakarta实现 :

struts.multipart.parser – 此属性应设置为扩展MultiPartRequest的类。 目前,该框架附带了Jakarta FileUpload实现。

您可以在Struts2官方网站或此处找到源代码(更快到google); 这是发布多部分表单时调用的内容:

  public void parse(HttpServletRequest request, String saveDir) throws IOException { try { setLocale(request); processUpload(request, saveDir); } catch (FileUploadBase.SizeLimitExceededException e) { if (LOG.isWarnEnabled()) { LOG.warn("Request exceeded size limit!", e); } String errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()}); if (!errors.contains(errorMessage)) { errors.add(errorMessage); } } catch (Exception e) { if (LOG.isWarnEnabled()) { LOG.warn("Unable to parse request", e); } String errorMessage = buildErrorMessage(e, new Object[]{}); if (!errors.contains(errorMessage)) { errors.add(errorMessage); } } } 

然后,这是循环多部分项目,文件和表单字段的地方:

  private void processUpload(HttpServletRequest request, String saveDir) throws FileUploadException, UnsupportedEncodingException { for (FileItem item : parseRequest(request, saveDir)) { if (LOG.isDebugEnabled()) { LOG.debug("Found item " + item.getFieldName()); } if (item.isFormField()) { processNormalFormField(item, request.getCharacterEncoding()); } else { processFileField(item); } } } 

这将在FileUploadBase中针对每个项目在此实现中结束:

  FileItemStreamImpl(String pName, String pFieldName, String pContentType, boolean pFormField, long pContentLength) throws IOException { name = pName; fieldName = pFieldName; contentType = pContentType; formField = pFormField; final ItemInputStream itemStream = multi.newInputStream(); InputStream istream = itemStream; if (fileSizeMax != -1) { if (pContentLength != -1 && pContentLength > fileSizeMax) { FileSizeLimitExceededException e = new FileSizeLimitExceededException( format("The field %s exceeds its maximum permitted size of %s bytes.", fieldName, fileSizeMax), pContentLength, fileSizeMax); e.setFileName(pName); e.setFieldName(pFieldName); throw new FileUploadIOException(e); } istream = new LimitedInputStream(istream, fileSizeMax) { @Override protected void raiseError(long pSizeMax, long pCount) throws IOException { itemStream.close(true); FileSizeLimitExceededException e = new FileSizeLimitExceededException( format("The field %s exceeds its maximum permitted size of %s bytes.", fieldName, pSizeMax), pCount, pSizeMax); e.setFieldName(fieldName); e.setFileName(name); throw new FileUploadIOException(e); } }; } stream = istream; } 

正如您所看到的,它处理文件大小上限和请求大小上限的方式完全不同;

我看了很有趣的源代码,但你可以确认(或纠正)这些假设,尝试调试MultiPartRequestWrapper,看看里面发生的是我认为发生的事情……祝你好运,玩得开心。

这是我如何解决这个问题。 我不会称之为解决方案。

在此处输入图像描述

尝试在早期阶段进行javascript检查: