Utilizo la biblioteca Apache commons fileupload 1.4 en mi proyecto java. Tengo una parte html con un formulario clásico con una entrada de archivo y algunos campos ocultos.

Tengo un problema con la carga de archivos de alrededor de> 500ko solo con Firefox> = 52

Funciona bien con archivos de 10mo en Chrome o Internet Explorer. Pero con Firefox, tengo un tiempo de espera después de esperar varios minutos después de enviar el formulario.

Después de algunas depuraciones, veo que el código responsable del tiempo de espera es:

List<FileItem> items = (new ServletFileUpload(new DiskFileItemFactory())).parseRequest(request);

La parte con causa espera es "parseRequest".

Intento depurar el contenido de la solicitud con el depurador en IntelliJ, pero no hay forma de copiar todo el valor del contenido de este objeto de solicitud en formato sin formato.

Funciona en estos casos: - Firefox: versión <= 52 o tamaño de archivo <500ko (alrededor, no es realmente preciso) - Internet Explorer - Chrome

No hay límite de tamaño de archivo, parece que depende del tamaño de la solicitud, porque la parte de solicitud de análisis está tomando demasiado tiempo ...

Recibo la solicitud HTTP con una extensión de Firefox en dos casos. Uno genera cargar un archivo de 3mo que no funciona (el archivo de solicitud es enorme, 3 veces el tamaño del archivo cargado): https://code.empreintesduweb.com/13561.html

Uno generó la carga de un archivo de 200ko que funciona (el archivo de solicitud es pequeño): https://code.empreintesduweb.com/13560.html

De hecho, la principal diferencia es que en Chrome o IE, no tengo el contenido sin procesar del archivo cargado en los encabezados de solicitud:

La parte con: obj stream .... endstream endobj

Solo aparece con Firefox ...

8
user2178964 10 may. 2019 a las 14:44

4 respuestas

La mejor respuesta

Gracias por toda tu respuesta. Finalmente, resolví este problema con éxito, pero de hecho ... en realidad no. Noté que había algunas cosas específicas en mi forma. Tenía dos entradas, una entrada de archivo estándar y otra que reciben el contenido del archivo codificado en base64 por algunos js extraños antes de cualquier carga. Así que una vez estaba teniendo el contenido en bruto del archivo, y también el archivo en base64. Por qué ?! No lo sé.

Pero elimino todo esto, creo un nuevo formulario simple y limpio con un archivo de entrada estándar. Utilizo la API de transmisión de ServletFileUpload, y funciona, y solo toma unos segundos para archivos grandes.

Así que no entiendo todo (por qué el problema solo estaba en algunos navegadores, por ejemplo), pero encuentro una solución;)

¡Gracias!

0
user2178964 4 jun. 2019 a las 21:06

Puede intentar establecer el tamaño máximo del archivo, tal vez el tamaño del archivo exceda el umbral máximo. Según documentación:

  • Los elementos cargados deben conservarse en la memoria siempre que sean razonablemente pequeños.
  • Los elementos más grandes deben escribirse en un archivo temporal en el disco.
  • No se deben permitir solicitudes de carga muy grandes.
  • Los valores predeterminados integrados para el tamaño máximo de un elemento que se conservará en la memoria, el tamaño máximo permitido de una carga solicitud y la ubicación de los archivos temporales son aceptables.

Intenta lo siguiente:

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // Set factory constraints
           DiskFileItemFactory factory = new DiskFileItemFactory();
           factory.setSizeThreshold(yourMaxMemorySize);
           ServletContext servletContext = this.getServletConfig().getServletContext();
           File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
           factory.setRepository(repository);
            List<FileItem> items = new ServletFileUpload(factory).parseRequest(request);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    // Process regular form field (input type="text|radio|checkbox|etc", select, etc).
                    String fieldName = item.getFieldName();
                    String fieldValue = item.getString();
                    // ... (do your job here)
                } else {
                    // Process form file field (input type="file").
                    String fieldName = item.getFieldName();
                    String fileName = FilenameUtils.getName(item.getName());
                    InputStream fileContent = item.getInputStream();
                    // ... (do your job here)
                }
            }
        } catch (FileUploadException e) {
            throw new ServletException("Cannot parse multipart request.", e);
        }

        // ...
    }

Aquí, proporcionamos una ubicación temporal para el archivo ya que el archivo es grande.

2
Ananthapadmanabhan 14 may. 2019 a las 16:35

Intente esto para establecer el tiempo de espera de la sesión utilizando el método setMaxInactiveInterval

 request.getSession().setMaxInactiveInterval(1200);

parámetro Especifica el tiempo, en segundos, entre las solicitudes del cliente antes de que el contenedor de servlet invalide esta sesión. Un valor de intervalo de cero o menos indica que la sesión nunca debe agotar el tiempo de espera.

1
Niravdas 18 may. 2019 a las 12:29

Algunas cosas que vale la pena probar aquí:

También podemos ayudarlo mejor si proporciona más información, como las versiones de apache / java / servlet, y algunos códigos más (especialmente la definición de request)

Algunos recursos que podrían ser útiles:
XMLHttpRequest
Sending_files_using_a_Formata__objetivo ¿Cómo establecer un encabezado para una solicitud HTTP GET y activar la descarga de archivos?

2
olinox14 16 may. 2019 a las 07:19