Java中的内存高效文件/图像上传?

时间:2013-08-29 14:36:12

标签: java servlets grails grails-2.0

我想将2MB - 10MB的图像上传到我的服务器并直接保存到硬盘。我的目标是尽可能多地保存JVM的堆内存,因为如果用户同时上传我的系统不应该崩溃。

这就是我现在这样做的方式。当带有上传的请求进入我的控制器时,我会这样做:

CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image')
InputStream inputStream = file.inputStream
byte [] byteFile = inputStream.getBytes()

try{
  def fullPath = // some image path and file name
  def newFile = new FileOutputStream(fullPath)
  newFile.write(byteFile)
  newFile.close()
}
catch(IOException e){ }

Here我读到有ImageIO和java.awt.Toolkit,其中Toolkit应该是存储文件最快的。

如何改进上传以尽可能少地使用堆并尽可能快地上传?

备选方案1:

另一种选择可能是:

CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image')
def fullPath = // some image path and file name
file.transferTo(new File(fullPath))

哪一个更好?

2 个答案:

答案 0 :(得分:2)

您当前的代码会收到包​​含文件内容的输入流,但会在将该流写入磁盘上的文件之前将该流的全部内容缓存在byte[]中。您的“替代1”直接从输入流流式传输到磁盘上的文件,因此内存效率会更高,并且至少与您当前的缓冲方法一样快(可能更快,因为沿途收集的垃圾更少)。

答案 1 :(得分:0)

如果您使用commons-fileupload lib并在流模式下使用 docs here),您将永远不再需要在内存中保留比您想要的更多的传入文件至。当请求来自客户端并迭代每个项目时,您会为每个表单字段或上传文件获取一个InputStream,并且可以使用该InputStream执行任何操作,例如将其写入文件(并包括抛出异常)如果用户尝试上传,例如,当您的限制为20MB或其他任何情况时上传2GB文件。

使用commons-fleupload的流API的唯一缺点是,处理常规表单字段也必须通过InputStream完成,但这可以通过调用lib的Streams.asString()轻松完成。