es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La respuesta del servlet se ignora al cargar un archivo grande en Apache FileUpload.

Estoy experimentando un comportamiento extraño al usar Apache FileUpload con límite de tamaño de archivo y el servidor de aplicaciones web Tomcat (versión 9). Aquí está mi código:

“`java
List multi = null;

try {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(System.getProperty(“java.io.tmpdir”)));

ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(2 * 1024 * 1024); // 2MB
upload.setHeaderEncoding("UTF-8");
multi = upload.parseRequest(request);

...

} catch (Exception e) {
e.printStackTrace();
}

// enviar respuesta del servlet

Como se puede ver arriba, el límite de tamaño de archivo es de 2MB.

Si subo un archivo de 1MB, todo está bien, mi respuesta del servlet se envía al cliente.

Si subo un archivo de 3MB, el comportamiento es correcto: se lanza una excepción y mi respuesta del servlet se envía al cliente.

Si subo un archivo de 10MB, el comportamiento NO es correcto. Se lanza la excepción pero mi respuesta del servlet nunca se envía al cliente. WireShark me muestra que Tomcat responde con un mensaje RST y luego el cliente intenta enviar la solicitud una y otra vez.

Después de mucho depurar, pude ver que pude evitar el código de reinicio (RST) al configurar el atributo del conector maxSwallowSize (definido en server.xml) a -1, o a un valor más grande que 10MB.

Todo está bien si elimino la llamada a setFileSizeMax().

Mis preguntas son:
– ¿Por qué el comportamiento es diferente en archivos de 3MB y 10MB si ambos son más grandes que el límite de 2BM?
– ¿Cuál es el papel de maxSwallowSize cuando el archivo es más pequeño/más grande que el límite?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Comportamiento en diferentes tamaños de archivos

    El comportamiento es diferente para archivos de 3MB y 10MB debido al mecanismo subyacente utilizado por Tomcat para manejar la carga de archivos. Cuando se carga un archivo utilizando Apache FileUpload, Tomcat lee el archivo en memoria y luego lo escribe en disco. Sin embargo, si el tamaño del archivo es mayor que el atributo de conector maxSwallowSize, Tomcat se negará a leer todo el archivo en memoria y cerrará inmediatamente la conexión con un mensaje de reinicio (RST). Este comportamiento está destinado a proteger al servidor de ataques DoS donde los archivos grandes podrían causar una denegación de servicio al consumir toda la memoria disponible. Por lo tanto, en el caso de un tamaño de archivo de 3MB, el archivo aún se lee en memoria y se escribe en disco correctamente antes de que se lance la excepción debido a que se excede el límite de tamaño de archivo. Sin embargo, en el caso de un tamaño de archivo de 10MB, se envía el mensaje RST antes de que el archivo se haya leído completamente en memoria o se haya escrito en disco, lo que hace que el cliente envíe repetidamente la solicitud.

    Rol de maxSwallowSize

    maxSwallowSize es un atributo de conector definido en server.xml que especifica la cantidad máxima de bytes que Tomcat aceptará de una solicitud del cliente si el tamaño de la solicitud supera el tamaño máximo permitido de solicitud configurado en el conector. Si el tamaño de la solicitud supera este límite, Tomcat cerrará la conexión y enviará un mensaje RST al cliente. Este atributo se aplica a cualquier solicitud, independientemente de si incluye una carga de archivo, ya que está destinado a proteger al servidor de ataques DoS limitando la cantidad de memoria que puede consumir una sola solicitud. En este caso, establecer maxSwallowSize en un valor mayor que el límite de tamaño de archivo permite que Tomcat lea todo el archivo en memoria y lo escriba en disco antes de enviar el mensaje RST. Establecer maxSwallowSize en -1 deshabilita por completo este comportamiento, lo que significa que Tomcat intentará leer toda la solicitud en memoria independientemente de su tamaño. Es importante encontrar un equilibrio entre proteger al servidor de ataques DoS y permitir que se procesen solicitudes legítimas.

Comments are closed.