【问题标题】:Post large amount of data with Wicket.ajax.post使用 Wicket.ajax.post 发布大量数据
【发布时间】:2014-10-21 05:48:54
【问题描述】:

我正在尝试使用 Behavior 和 JavaScript FileReader,如以下问题所示:Wicket Drag and drop functionality for adding an image

如果我发布超过 200k,我会收到错误 Form too large。所以也许我错过了一些多部分的东西。

使用大量数据调用Wicket.ajax.post() 的正确方法是什么?

我尝试将mp 设置为true,但随后它开始抱怨我没有表单ID。需要表格吗?

顺便说一句。我使用 Jetty,但是使用表单进行常规文件上传没有问题。

【问题讨论】:

    标签: ajax post file-upload wicket


    【解决方案1】:

    此错误来自码头Request 实现。

    如果您查看Request#extractFormParameters 方法的来源,您将看到以下内容:

    if (_context != null)
    {
        maxFormContentSize = _context.getContextHandler().getMaxFormContentSize();
        maxFormKeys = _context.getContextHandler().getMaxFormKeys();
    }
    
    if (maxFormContentSize < 0)
    {
       Object obj = _channel.getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
       if (obj == null)
          maxFormContentSize = 200000;
       else if
          ...
    }
    

    所以,实际上,您可以真正将您的上下文值设置为 pikand 建议的0,或者设置服务器配置如下:

    <Configure id="Server" class="org.eclipse.jetty.server.Server">
        <Call name="setAttribute">
          <Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
          <Arg>-1<!-- or 0, or any lt 0 --></Arg>
        </Call>
        ...
    </Configure>
    

    根据此代码稍后会抛出您的异常:

    if (contentLength > maxFormContentSize && maxFormContentSize > 0)
    {
        throw new IllegalStateException("Form too large: " + contentLength + " > " + maxFormContentSize);
    }
    

    所以,你可以看到,maxFormContentSize 可能是&lt;= 0 不抛出这个异常。

    我认为,没有必要通过 ajax 进行更新。但实际上最好限制数据大小,而不是让用户放下你的服务器。

    其他应用程序服务器有自己的设置,对于大多数应用程序服务器,您应该将maxPostSize 值设置为零,以禁用此限制。


    另外,检票口Form 组件有它自己的maxSize 属性,你可以用Form#setMaxSize 设置它。问题是Form 将此值作为Bytes 值传输到FileUploadBase 类,该类具有下一个javadoc:

    完整请求允许的最大大小,而不是 文件大小最大值。 -1 值表示没有最大值。

    实际上这个参数是通过fileUpload.setSizeMax(maxSize.bytes());设置的,Bytes不能保持负值。但我认为您可以尝试将其设置为0 并检查它是否有效。默认情况下,Form#getSizeMax() 方法检查:

    return getApplication().getApplicationSettings().getDefaultMaximumUploadSize();
    

    返回Bytes.MAX,等于8388608 terabytes。我认为,这将是“无限制”值:)

    另外,据我所知 - 您无需设置表单 ID,即可使用 multipart 参数。仅当您通过 ajax 更新表单时,您必须设置 Form.setOutputMarkupId(true)。但实际上Form如果是multipart的话,会在renderHead方法中自己创建id:

    // register some metadata so we can later properly handle multipart ajax posts for
    // embedded forms
    registerJavaScriptNamespaces(response);
    response
        .render(JavaScriptHeaderItem.forScript("Wicket.Forms[\"" + getMarkupId()
            + "\"]={multipart:true};", Form.class.getName() + '.' + getMarkupId()
            + ".metadata"));
    

    注意,getMarkupId() 方法会在不存在的情况下创建标记 ID。

    【讨论】:

    • 哇,感谢迈克尔的分析。我看到我可以通过将值设置为 -1 或 0 来“解决”这个问题。你知道为什么他们会允许上传 >2MB 的文件,但不允许上传 ajax 帖子吗?还是Wicket在使用form.setMaxSize()时在请求上设置maxFormContentSize?
    • @RobAu,另外,正如我所见,如果使用了multipart 请求,那么码头Request 不会通过调用extractMultipartParameters 方法和检票口Form 来检查maxFormSize在某些情况下可以自动检测是否为multipart(检查Form#isMultiPart方法)。因此,即使您不知道,也可以绕过此限制。
    【解决方案2】:

    Jetty 中的表单大小限制默认为 200k。 在您的 webapp/WEB-INF 文件夹中添加 jetty-web.xml。您可以在此处设置所需大小的表单大小限制。

    <?xml version="1.0"?>
      <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
      "http://jetty.mortbay.org/configure.dtd">
    
      <Configure id="WebAppContext" class="org.eclipse.jetty.webapp.WebAppContext">
              <Set name="maxFormContentSize" type="int">900000</Set>
              <Set name="maxFormKeys">5000</Set>
      </Configure>
    

    【讨论】:

    • 虽然这可能会解决我的码头问题,但我希望得到一个更结构化的答案,因为文件上传不受此大小的限制。所以它们的传输方式不同(但仍然使用 post),所以我希望我能以某种方式从 ajax 调用中模仿这种行为。我只是不知道如何或在哪里看
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    相关资源
    最近更新 更多