Search code examples
javaajaxtomcatservletsapache-commons-fileupload

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


I have an Ajax POST call that uploads one or more files to a servlet.

In my servlet, I use Commons FileUpload library to manage the uploading file process:

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); 
    }
    
}

When I catch the exception outside the getRequestInfoMultipart method, I'm writing in the http response a JSon object with two parameters (result and message):

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;
    }
}

After that, the Ajax call should get the response in the success block, but instead, the http request is being repeated and then, the Ajax call is entering in the error block, so I can't show the result to the user but a generic error message.

Does anybody know why request is being repeated and why the Ajax call is ending with error?

Thank you very much. Quique.


Solution

  • Finally I found the error and it was nothing to do with Ajax or servlet code, but with Tomcat default connector maxSwallowSize property:

    When somebody uploads a file that Tomcat knows is greater than maximum size allowed, Tomcat aborts the upload. Then, Tomcat does not swallow the body and the client is unlikely to see the response. So, it seems the request is repeated and finally a connection reset occurs and ajax received a 0 error code and none information from servlet.

    In development you can set the property as unlimited with -1 value in the server.xml file:

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

    In production, you must set an appropiate value for your interests.

    Doing that, server will response after process all the body from client. But keep in mind that if a client uploads a file greter than the maxSwallowSize, you will get the same behavior.