docs: @Nonnull
    public static EChange handleMultipartFormData (@Nonnull final HttpServletRequest aHttpRequest,
                                                   @Nonnull final BiConsumer <String, Object> aConsumer)
    {
      if (aHttpRequest instanceof MockHttpServletRequest)
      {
        // First check, because some of the contained methods throw
        // UnsupportedOperationExceptions
        return EChange.UNCHANGED;
      }
  
      if (!RequestHelper.isMultipartFormDataContent (aHttpRequest))
      {
        // It's not a multipart request
        return EChange.UNCHANGED;
      }
  
      // It is a multipart request!
      // Note: this handles only POST parameters!
      boolean bAddedFileUploadItems = false;
  
      try
      {
        // Setup the ServletFileUpload....
        final ServletFileUpload aUpload = new ServletFileUpload (s_aFIFP.getFileItemFactory ());
        aUpload.setSizeMax (MAX_REQUEST_SIZE);
        aUpload.setHeaderEncoding (CWeb.CHARSET_REQUEST_OBJ.name ());
        final IProgressListener aProgressListener = ProgressListenerProvider.getProgressListener ();
        if (aProgressListener != null)
          aUpload.setProgressListener (aProgressListener);
  
        try
        {
          aHttpRequest.setCharacterEncoding (CWeb.CHARSET_REQUEST_OBJ.name ());
        }
        catch (final UnsupportedEncodingException ex)
        {
          if (LOGGER.isErrorEnabled ())
            LOGGER.error ("Failed to set request character encoding to '" + CWeb.CHARSET_REQUEST_OBJ.name () + "'", ex);
        }
  
        // Group all items with the same name together
        final IMultiMapListBased <String, String> aFormFields = new MultiHashMapArrayListBased <> ();
        final IMultiMapListBased <String, IFileItem> aFormFiles = new MultiHashMapArrayListBased <> ();
        final ICommonsList <IFileItem> aFileItems = aUpload.parseRequest (aHttpRequest);
        for (final IFileItem aFileItem : aFileItems)
        {
          if (aFileItem.isFormField ())
          {
            // We need to explicitly use the charset, as by default only the
            // charset from the content type is used!
            aFormFields.putSingle (aFileItem.getFieldName (), aFileItem.getString (CWeb.CHARSET_REQUEST_OBJ));
          }
          else
            aFormFiles.putSingle (aFileItem.getFieldName (), aFileItem);
        }
  
        // set all form fields
        for (final Map.Entry <String, ICommonsList <String>> aEntry : aFormFields.entrySet ())
        {
          // Convert list of String to value (String or String[])
          final ICommonsList <String> aValues = aEntry.getValue ();
          final Object aValue = aValues.size () == 1 ? aValues.getFirst () : ArrayHelper.newArray (aValues, String.class);
          aConsumer.accept (aEntry.getKey (), aValue);
        }
  
        // set all form files (potentially overwriting form fields with the same
        // name)
        for (final Map.Entry <String, ICommonsList <IFileItem>> aEntry : aFormFiles.entrySet ())
        {
          // Convert list of String to value (IFileItem or IFileItem[])
          final ICommonsList <IFileItem> aValues = aEntry.getValue ();
          final Object aValue = aValues.size () == 1 ? aValues.getFirst ()
                                                     : ArrayHelper.newArray (aValues, IFileItem.class);
          aConsumer.accept (aEntry.getKey (), aValue);
        }
  
        // Parsing complex file upload succeeded -> do not use standard scan for
        // parameters
        bAddedFileUploadItems = true;
      }
      catch (final FileUploadException ex)
      {
        if (!StreamHelper.isKnownEOFException (ex.getCause ()))
          LOGGER.error ("Error parsing multipart request content", ex);
      }
      catch (final RuntimeException ex)
      {
        LOGGER.error ("Error parsing multipart request content", ex);
      }
      return EChange.valueOf (bAddedFileUploadItems);
    }