8 votes

Apache commons fileupload timeout only with Firefox

J'utilise la bibliothèque Apache commons fileupload 1.4 dans mon projet Java. J'ai une partie html avec un formulaire classique avec un champ de fichier et quelques champs cachés.

J'ai un problème avec le téléchargement de fichiers d'environ >500ko uniquement avec Firefox >= 52

Cela fonctionne bien avec des fichiers de 10mo dans Chrome ou Internet Explorer. Mais avec Firefox, j'ai une expiration après avoir attendu plusieurs minutes après avoir soumis le formulaire.

Après quelques debuggages, je vois que le code responsable de l'expiration est :

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

La partie qui cause l'attente est "parseRequest".

J'essaie de déboguer le contenu de la requête avec le débogueur dans IntelliJ, mais il n'y a aucun moyen de copier la valeur du contenu entier de cet objet requête au format brut.

Cela fonctionne dans ces cas : - Firefox : version <= 52 ou taille du fichier < 500ko (environ, ce n'est pas très précis) - Internet Explorer - Chrome

Il n'y a pas de limite de taille de fichier, il semble que cela dépend de la taille de la requête, car la partie d'analyse de la requête prend trop de temps...

Je reçois la requête HTTP avec une extension Firefox dans deux cas. L'un générant le téléchargement d'un fichier de 3mo qui ne fonctionne pas (le fichier de requête est énorme, 3x la taille du fichier téléchargé) : https://code.empreintesduweb.com/13561.html

L'autre généré en téléchargeant un fichier de 200ko qui fonctionne (le fichier de requête est petit) : https://code.empreintesduweb.com/13560.html

En fait, la principale différence est que dans Chrome ou IE, je n'ai pas le contenu brut du fichier téléchargé dans les en-têtes de la requête :

La partie avec : obj stream .... endstream endobj

Apparaît uniquement avec Firefox...

2voto

olinox14 Points 2960

Quelques choses qui valent la peine d'être essayées ici :

Nous pourrions également mieux vous aider si vous fournissez quelques informations supplémentaires, comme les versions d'apache / java / servlet, et un peu plus de code (surtout la définition de request)

Quelques ressources qui pourraient être utiles :
XMLHttpRequest
Sending_files_using_a_FormData_object
How to set a header for a HTTP GET request, and trigger file download?

2voto

Ananthu Points 1

Vous pouvez essayer de définir la taille maximale du fichier, peut-être que la taille du fichier dépasse le seuil maximum. Selon la documentation :

  • Les éléments téléchargés doivent être conservés en mémoire tant qu'ils sont raisonnablement petits.
  • Les éléments plus volumineux doivent être écrits dans un fichier temporaire sur le disque.
  • Les demandes de téléchargement très volumineuses ne devraient pas être autorisées.
  • Les valeurs par défaut pour la taille maximale d'un élément à conserver en mémoire, la taille maximale autorisée d'une demande de téléchargement et l'emplacement des fichiers temporaires sont acceptables.

Essayez ce qui suit :

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            // Définir les contraintes de l'usine
           DiskFileItemFactory factory = new DiskFileItemFactory();
           factory.setSizeThreshold(votreTailleMemoireMax);
           ServletContext servletContext = this.getServletConfig().getServletContext();
           File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
           factory.setRepository(repository);
            List items = new ServletFileUpload(factory).parseRequest(request);
            for (FileItem item : items) {
                if (item.isFormField()) {
                    // Traiter le champ de formulaire régulier (type d'entrée="text|radio|checkbox|etc", select, etc).
                    String fieldName = item.getFieldName();
                    String fieldValue = item.getString();
                    // ... (faire votre travail ici)
                } else {
                    // Traiter le champ de fichier de formulaire (type d'entrée="file").
                    String fieldName = item.getFieldName();
                    String fileName = FilenameUtils.getName(item.getName());
                    InputStream fileContent = item.getInputStream();
                    // ... (faire votre travail ici)
                }
            }
        } catch (FileUploadException e) {
            throw new ServletException("Impossible d'analyser la demande multipart.", e);
        }

        // ...
    }

Ici, nous fournissons un emplacement temporaire pour le fichier car le fichier est volumineux.

1voto

Niravdas Points 133

Essayez ceci pour définir le timeout de session en utilisant la méthode setMaxInactiveInterval

 request.getSession().setMaxInactiveInterval(1200);

Le paramètre spécifie le temps, en secondes, entre les requêtes du client avant que le conteneur de servlet n'invalide cette session. Une valeur d'intervalle de zéro ou moins indique que la session ne devrait jamais expirer.

0voto

user2178964 Points 521

Merci pour toutes vos réponses. Enfin, j'ai réussi à résoudre ce problème, mais en fait... pas vraiment. J'ai remarqué qu'il y avait des choses spécifiques dans mon formulaire. J'avais deux entrées, une entrée de fichier standard et une autre qui recevait le contenu du fichier encodé en base64 par un code JavaScript bizarre avant tout téléchargement. Ainsi, j'avais une fois le contenu brut du fichier et aussi le fichier en base64. Pourquoi ? Je ne sais pas.

Mais j'ai supprimé tout cela, j'ai créé un nouveau formulaire simple et propre avec une entrée de fichier standard. J'ai utilisé l'API de flux de ServletFileUpload, et cela fonctionne, et prend seulement quelques secondes pour les gros fichiers.

Donc je ne comprends pas tout (pourquoi le problème n'était que sur certains navigateurs par exemple), mais j'ai trouvé une solution ;)

Merci !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X