问题解决了 !
从更新的文档中,现在可以使用新的JakartaStreamMultiPartRequest解决问题:
从 Struts 版本2.3.18开始,添加了 MultiPartRequest 的新实现 - JakartaStreamMultiPartRequest。它可用于处理大文件,更多详细信息请参见WW-3025,但您可以简单设置
<constant name="struts.multipart.parser" value="jakarta-stream" />
在 struts.xml 中开始使用它。
从链接的 JIRA 正文:
当任何大小限制超出时,立即抛出 FileUploadBase.SizeLimitExceededException 或 FileUploadBase.FileSizeLimitExceededException 并终止多部分请求的解析,而不提供请求参数以进行进一步处理。
这基本上使得任何 Web 应用程序都无法优雅地处理超出大小限制的情况。
我的建议是请求解析应该始终完成以传递请求参数。可能会收集超出大小限制的情况/异常以供以后检索,应将 FileSizeLimitExeededException 映射到 FileItem 以允许在应用程序级别对 FileItem 进行一些验证。如果上传的文件太大,这将允许将上传输入字段标记为错误。
实际上我为此做了一个补丁(见附件)。使用此补丁,commons-fileupload 总是在超出大小限制的情况下完成请求解析,并且只有在完成解析后如果检测到异常才会抛出异常。
和克里斯克兰福德的评论:
我正在为 Struts2 开发一个新的多部分解析器,我正在调用 JakartaStreamMultiPartRequest。
这个多部分解析器的行为与现有的 Jakarta 多部分解析器相同,只是它使用 Commons FileUpload Streaming API 并且不是将最大请求大小检查委托给 File Upload API,而是在内部完成以避免 Upload API 的现有问题打破循环迭代和参数丢失。
太棒了,谢谢大家:)
旧答案
我想这是由于不同的行为
- 超过其最大定义大小的单个文件(或多个文件),然后可以在正常进程结束时使用 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 以查看内部发生的事情是否是我认为正在发生的事情......祝你好运并玩得开心。