5

Ich bekomme OutOfMemoryErrors beim Hochladen von großen (> 300MB) Dateien zu ein Servlet mit Commons FileUpload 1.2.1. Es scheint seltsam, denn der gesamte Punkt der Verwendung von DiskFileItem ist zu verhindern, dass die (möglicherweise große) Datei im Speicher residiert. Ich verwende die Standardgröße Schwelle von 10KB, also das ist alles, was jemals in den Haufen geladen werden sollte, richtig? Hier ist die Teilstapelspur:Wie kann ich OutOfMemoryErrors vermeiden, wenn ich mit dem DiskFileItem von Commons FileUpload große Dateien hochlade?

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) 

Warum passiert das? Gibt es eine Konfiguration, die ich vermisse? Irgendwelche Tipps/Tricks, um diese Situation zu vermeiden neben dem Erhöhen meiner Heap-Größe?

Ich sollte wirklich nicht meinen Heap erhöhen müssen, weil in der Theorie die meisten, die von dieser Operation in Speicher geladen werden sollten, etwas über 10 KB sind. Plus, mein Heap Max (-Xmx) ist bereits für 1GB gesetzt, was reichlich sein sollte.

Antwort

10

Bei Dateiuploads, besonders großen, sollten Sie diese Dateien als Streams verarbeiten, die Sie in einen mittelgroßen In-Memory-Puffer schlürfen und direkt in Ihre Ausgabedatei kopieren. Der falsche Weg, dies zu tun, ist das ganze Ding in die Erinnerung einzuatmen, bevor man es ausschreibt.

The doc on commons-upload erwähnt, nur unter der Mitte, wie man "Datei hochladen". Wenn Sie daran denken, aus dem Inputstream in vernünftige Chunks (etwa 1 MB) in den Outputstream zu kopieren, sollten Sie kein Problem haben.

+1

Zuerst habe ich Ihren Kommentar zu meiner Situation nicht angewendet denken weil ich die Datei nicht direkt verarbeitet habe; Ich habe die FileItem-Instanzen in die MultipartFile-Klasse von Spring eingebunden. Ich schaute mir den Code jedoch genauer an und rief getBytes() von MultipartFile auf, das den gesamten Inhalt der Datei zurückgibt. Ich habe mein FileItem aus MultipartFile ausgepackt und dann die Dateien wie in der Dokumentation empfohlen verarbeitet. Das hat mein Problem gelöst. – rcampbell

Verwandte Themen