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

Rob*_*ell 5 java heap servlets out-of-memory apache-commons-fileupload

使用Commons FileUpload 1.2.1将大型(> 300MB)文件上传到servlet时,我得到OutOfMemoryErrors.这看起来很奇怪,因为使用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)
Run Code Online (Sandbox Code Playgroud)

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

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

Car*_*icz 10

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

关于commons-upload的文档提到了中间,如何"处理文件上传".如果您记得以合理大小的块(例如,1 MB)从输入流复制到输出流,那么您应该没有问题.