当抛出 FileUploadBase.SizeException (FileUploadException) 时,似乎重复了请求(使用 Commons FileUpload)

When FileUploadBase.SizeException (FileUploadException) is thrown, it seems the request is repeated (using Commons FileUpload)

我有一个 Ajax POST 调用将一个或多个文件上传到 servlet。

在我的 servlet 中,我使用 Commons FileUpload 库来管理上传文件过程:

private RequestInfo getRequestInfoMultipart(HttpServletRequest request, HttpSession session) throws SupportException {

    RequestInfo multipartReqestInfo = new RequestInfo();

    try {

        DiskFileItemFactory factory = new DiskFileItemFactory();

        factory.setRepository(new File(TMP_DIR));

        ServletFileUpload upload = new ServletFileUpload(factory);

        upload.setFileSizeMax(MAX_SIZE_UPLOADED_FILE);

        List<FileItem> items = upload.parseRequest(request); // <-- Throws exception on max file size reached

        ...
        
        
    } catch (FileUploadException e) {
        throw new SupportException("SOP_EX00009"); 
    } catch (Exception e) {
        throw new SupportException("SOP_EX00001", e); 
    }
    
}

当我在 getRequestInfoMultipart 方法之外捕获到异常时,我在 http 响应中写入了一个带有两个参数(结果和消息)的 JSon 对象:

private RequestInfo getRequesInfo(HttpServletRequest request, HttpServletResponse response, HttpSession session, boolean isMultipart) {
    try {
        if (isMultipart) {
            return getRequestInfoMultipart(request, session);
        }
        return getRequestInfo(request, session);

    } catch (SupportException e) {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        try (PrintWriter writer = response.getWriter()) {
            JSonResult jsonResult = new JSonResult();
            jsonResult.setResult(KO);
            jsonResult.setMessage(e.getMessage());
            writer.print(new Gson().toJson(jsonResult));
            writer.flush();

        } catch (IOException ex) {
            log.error("Error getting PrintWriter", ex);
        }
        return null;
    }
}

在那之后,Ajax 调用应该在成功块中得到响应,但是 http 请求被重复 然后,Ajax 调用正在进入错误块,因此我无法向用户显示结果,只能显示一般错误消息。

有人知道为什么重复请求以及为什么 Ajax 调用以错误结束吗?

非常感谢。 奎克.

最后我发现了错误,它与 Ajax 或 servlet 代码无关,但与 Tomcat 默认连接器 maxSwallowSize 属性:

当有人上传 Tomcat 知道大于允许的最大大小的文件时,Tomcat 会中止上传。然后,Tomcat 不会吞下主体,客户端不太可能看到响应。因此,似乎重复了请求,最后发生了连接重置,ajax 从 servlet 收到了 0 错误代码和 none 信息。

在开发中,您可以在 server.xml 文件中使用 -1 值将 属性 设置为无限制:

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxSwallowSize="-1" />

在生产中,您必须根据自己的兴趣设置一个合适的值。

这样做,服务器将在处理完来自客户端的所有正文后做出响应。但请记住,如果客户端上传的文件大于 maxSwallowSize,您将得到相同的行为。