使用Commons FileUpload的DiskFileItem上传大文件时,如何避免OutOfMemoryErrors?

时间:2009-11-07 17:38:32

标签: java servlets heap out-of-memory apache-commons-fileupload

将大型(> 300MB)文件上传到时,我收到OutOfMemoryErrors 一个使用Commons FileUpload 1.2.1的servlet。这看起来很奇怪,因为 使用DiskFileItem的全部意义是防止(可能是 来自内存的大文件。我使用的是默认大小 阈值为10KB,这就是应该加载到的所有内容 堆,对吗?这是部分堆栈跟踪:

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)

为什么会这样?我缺少一些配置吗?任何提示/技巧,以避免这种情况除了增加我的堆大小

我真的不应该增加我的堆,因为理论上应该从这个操作加载到内存中的最多只是超过10KB。另外,我的堆最大值(-Xmx)已经设置为1GB,应该足够了。

2 个答案:

答案 0 :(得分:10)

在处理文件上传时,尤其是大文件上传时,您应该将这些文件作为流进行处理,然后将其插入到中等大小的内存缓冲区中并直接复制到输出文件中。做错的方法是在把它写出来之前将整个东西吸入记忆中。

The doc on commons-upload提到,正好在中间,如何“处理文件上传”。如果您记得以合理大小的块(例如,1 MB)从输入流复制到输出流,那么您应该没有问题。

答案 1 :(得分:0)

虽然Carl Smotricz在一般情况下的答案可能更好,但您得到的例外是此处报告的JVM错误:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6478546