Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/352.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java struts2文件上传松动参数_Java_File Upload_Struts2_Request_Multipartform Data - Fatal编程技术网

Java struts2文件上传松动参数

Java struts2文件上传松动参数,java,file-upload,struts2,request,multipartform-data,Java,File Upload,Struts2,Request,Multipartform Data,使用Struts 2.3.15.1 在struts2中实现文件上传。这是我已经做了很多次的事情,但是,我试图包括一些健全的检查(即最大文件大小)。我将fileUpload拦截器作为堆栈中的最后一个拦截器(即struts.xml)。我的堆栈包括一些内部拦截器以及验证工作流堆栈。我在我的struts.properties文件中设置了以下属性: struts.multipart.maxSize = 2000000 除了文件上传,我还在表单中传递一些其他参数。表格定义为: <s:form act

使用Struts 2.3.15.1

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

struts.multipart.maxSize = 2000000
除了文件上传,我还在表单中传递一些其他参数。表格定义为:

<s:form action="addResource" method="post" enctype="multipart/form-data"> 
  <s:hidden name="rfqId" value='%{rfq.id}' />
  <s:file name="uploadFile" id="uploadFile" label="File" size="40" value=""/>
  ....
</s:form>

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

我错过什么了吗

问题解决了! 从开始,现在可以使用新的JakartaStreamMultiPartRequest解决问题:

从Struts版本2.3.18开始多部分请求的新实现 已添加-JakartaStreamMultiPartRequest。它可以用来处理 大文件,请参阅以了解更多详细信息,但您可以简单地设置


在struts.xml中开始使用它

从链接的JIRA主体:

当任何尺寸限制超过时,立即 FileUploadBase.SizeLimitExceedeException或 将引发FileUploadBase.FileSizeLimitExceedeException并解析 多部分请求在不提供请求参数的情况下终止 以便进一步处理

这基本上使任何web应用程序都无法处理 大小限制正常地超过了大小限制

我的建议是,请求解析应该始终完成才能交付 请求参数。超出大小限制案例/异常可能为 为以后检索而收集,应删除FileSizeLimiteXeedexception 映射到FileItem以允许对上的FileItem进行某些验证 应用程序级别。这将允许将上载输入字段标记为 如果上载的文件太大,则会出错

实际上,我为此做了一个补丁(见附件)。有了这个补丁, commons fileupload总是在大小不同的情况下完成请求解析 限制超出,并且只有在完成解析后才会抛出 如果检测到异常,则为异常

克里斯·克兰福德的评论是:

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

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

太棒了,谢谢大家:)


旧答案

我猜这是由于不同的行为

  • 单个文件(或多个文件)超过其最大定义大小,然后可以在正常进程结束时将其重定向回输入结果,以及
  • 违反整个请求的最大大小,这将(可能?)破坏任何其他元素解析,因为这是一种安全机制,而不是像文件大小检查这样的功能
首先解析文件()时,如果文件超出了多部分请求大小的限制,则不会读取其他字段(表单字段),因此不会返回输入结果

对于MultiPartRequestWrapper:

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

你可以在Struts2官方网站上找到源代码(比谷歌更快);这就是发布多部分表单时的名称:

 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);
            }
        }
    }
最终,在本实施方案中,每个项目将:

 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检查:

<!DOCTYPE html>
<html>

    <head>
    <script type="text/javascript">
    function checkSize(max_img_size)
    {
        var input = document.getElementById("upload");
        // check for browser support (may need to be modified)
        if(input.files && input.files.length == 1)
        {           
            if (input.files[0].size > max_img_size) 
            {
                alert("The file must be less than " + (max_img_size/1024/1024) + "MB");
                return false;
            }
        }

        return true;
    }
    </script>
    </head>
    <body>
    <form action="demo_post_enctype.asp" method="post" enctype="multipart/form-data" 
    onsubmit="return checkSize(2097152)">    
    <input type="file" id="upload" />
    <input type="submit" />

    </body>
    </html>

功能检查大小(最大检查大小)
{
var input=document.getElementById(“上传”);
//检查浏览器支持(可能需要修改)
if(input.files&&input.files.length==1)
{           
if(input.files[0].size>max\u img\u size)
{
警报(“文件必须小于”+(最大img_大小/1024/1024)+“MB”);
返回false;
}
}
返回true;
}

是否有任何理由将
文件上传
拦截器作为堆栈中的最后一个拦截器?与其他位置相对还是根本不?它现在是在默认堆栈中还是什么?对于它的价值,我尝试了拦截器第一/中间/最后/等无效。拦截器的顺序很重要。
fileUpload
defaultStack
中,但不在
basicStack
中。您应该