2009-11-07 16 views
5

Otrzymuję OutOfMemoryErrors przy przesyłaniu dużych plików (> 300 MB) do serwletu wykorzystującego Commons FileUpload 1.2.1. Wydaje się to dziwne, ponieważ cały problem z używaniem DiskFileItem polega na tym, aby zapobiec przechowywaniu w pamięci (prawdopodobnie large) pliku. Używam domyślnego rozmiaru próg 10KB, więc to wszystko powinno być kiedykolwiek załadowane do sterty , prawda? Oto częściowy ślad stosu:Jak mogę uniknąć OutOfMemoryErrors podczas korzystania z FileFoldItem Commons FileUpload do przesyłania dużych plików?

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) 

Dlaczego tak się dzieje? Czy brakuje jakiejś konfiguracji? Wszelkie wskazówki/wskazówki, aby uniknąć tej sytuacji oprócz zwiększania mojego rozmiaru sterty?

Naprawdę nie powinienem zwiększać sterty, ponieważ teoretycznie to, co powinno być załadowane do pamięci z tej operacji, jest nieco ponad 10KB. Plus, mój heap max (-Xmx) jest już ustawiony na 1 GB, który powinien być dużo.

Odpowiedz

10

W przypadku przesyłania plików, zwłaszcza dużych, należy przetworzyć te pliki jako strumienie, które sąsiadują ze średnim rozmiarem w pamięci i kopiować bezpośrednio do pliku wyjściowego. Błędnym sposobem na to jest wdychanie całej rzeczy do pamięci przed jej zapisaniem.

The doc on commons-upload wspomina, tuż pod środkowym, jak "Przetwarzanie przesłania pliku". Jeśli pamiętasz, aby kopiować z wejścia do strumienia wyjściowego w porcjach o rozsądnej wielkości (powiedzmy 1 MB), nie powinieneś mieć problemu.

+1

Na początku nie myślałem komentarz stosowane do mojej sytuacji , ponieważ nie przetwarzałem pliku bezpośrednio; Pakowałem instancje FileItem w klasie Spring MultipartFile. Przyjrzałem się jednak bliżej kodowi i wywołałem funkcję getBytes() programu MultipartFile, która zwraca całą zawartość pliku. Rozpakowałem plik FileItem z pliku MultipartFile, a następnie przetworzyłem pliki zgodnie z zaleceniami w dokumentacji. To rozwiązało mój problem. – rcampbell

Powiązane problemy