2009-11-07 21 views
5

Je reçois OutOfMemoryErrors lors du téléchargement de gros fichiers (> 300 Mo) à une servlet utilisant Commons FileUpload 1.2.1. Il semble étrange, car l'ensemble du point d'utilisation DiskFileItem est d'empêcher le (peut-être grand) fichier à partir résidant en mémoire. J'utilise la taille par défaut seuil de 10 Ko, donc c'est tout ce qui devrait jamais être chargé dans le tas , non? Voici la trace de pile partielle:Comment puis-je éviter OutOfMemoryErrors lors de l'utilisation de DiskFileItem de Commons FileUpload pour télécharger des fichiers volumineux?

java.lang.OutOfMemoryError 
     at java.io.FileInputStream.readBytes(Native Method) 
     at java.io.FileInputStream.read(FileInputStream.java:177) 
     at org.apache.commons.fileupload.disk.DiskFileItem.get(DiskFileItem.java:334) 
     at org.springframework.web.multipart.commons.CommonsMultipartFile.getBytes(CommonsMultipartFile.java:114) 

Pourquoi cela se produit-il? Y a-t-il une configuration qui me manque? Tous les conseils/astuces pour éviter cette situation en plus d'augmenter ma taille de tas?

je ne devrais pas avoir à augmenter mon tas, car en théorie le plus qui doit être chargé dans la mémoire de cette opération est un peu plus de 10 Ko. De plus, mon tas max (-Xmx) est déjà réglé pour 1Go ce qui devrait être suffisant.

Répondre

10

Lorsque vous traitez avec le téléchargement de fichiers, en particulier les grands, vous devriez traiter ces fichiers sous forme de flux que vous Slurp dans un milieu de taille tampon en mémoire et les copier directement dans votre fichier de sortie. La mauvaise façon de le faire est d'inhaler le tout en mémoire avant de l'écrire.

The doc on commons-upload mentionne, juste en dessous du milieu, comment « traiter un téléchargement de fichier ». Si vous pensez copier du flux d'entrée vers le flux de sortie en morceaux de taille raisonnable (disons 1 Mo), vous ne devriez pas avoir de problème.

+1

Au début, je ne pensais pas que votre commentaire appliqué à ma situation , parce que je ne traitais pas le fichier directement; Je enveloppais les instances FileItem dans la classe MultipartFile de Spring. J'ai regardé plus attentivement le code, cependant, et il appelait getBytes() de MultipartFile qui retourne tout le contenu du fichier. J'ai déballé mon FileItem de MultipartFile, puis j'ai traité les fichiers comme recommandé dans la documentation. Cela a résolu mon problème. – rcampbell