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

Java中内存高效的文件/图像上传?,java,servlets,grails,grails-2.0,Java,Servlets,Grails,Grails 2.0,我想上传2MB-10MB的图像到我的服务器上,并将它们直接保存到硬盘上。目标是尽可能地节省JVM的堆内存,因为如果用户同时上传,我的系统不会崩溃 我现在就是这样做的。当上传请求进入我的控制器时,我会: CommonsMultipartFile file = (CommonsMultipartFile) request.getFile('image') InputStream inputStream = file.inputStream byte [] byteFile = inputStream

我想上传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){ }
我读到有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))

哪一个更好?

如果您使用commons fileupload lib并在流模式()下使用它,您将永远不必在内存中保存任何超出您想要的传入文件。当请求从客户端传入,并且您迭代每个项目时,您将获得每个表单字段或上载文件的InputStream,并且可以使用该InputStream执行任何操作,例如将其写入文件(包括在用户尝试上载时引发异常,例如,当您的限制为20MB或其他限制时,如果用户尝试上载2GB文件)


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

您当前的代码会收到一个包含文件内容的输入流,然后将该流的全部内容缓冲在
字节[]
中,然后再将其写入磁盘上的文件。您的“备选方案1”从输入流直接流到磁盘上的文件,因此内存效率更高,至少与您当前的缓冲方法一样快(可能更快,因为在此过程中收集的垃圾更少)。

您可以将commons fileupload流的代码放入吗?当我做file.inputStream时,这不是你的意思吗?另外,我更新了我的帖子,第二种选择更好吗?我的选择1与此相同吗?它也一样快吗?@stephan1001使用
transferTo
应该是做你想做的事情的最快方式。Commons fileupload缓冲内存中的小上载,并将较大的上载流到磁盘上的临时文件。如果文件已在内存中缓冲,则调用
transferTo
将转储缓冲区;如果可以,则重命名临时文件;如果不能,则执行从临时文件到目标文件的流式复制。让框架使用其“内部知识”为每个文件选择最有效的方法永远不会比自己选择一种方法并无条件地使用它慢。编码是我必须注意的事情吗?如果是这样,我如何确保输入文件的编码为UTF-8?@stephan1001否,字符编码仅适用于文本数据,图像为纯二进制数据,
transferTo
仅将上载的字节保存到文件中,而不考虑这些字节代表什么。@stephan1001否,字符编码仅适用于文本数据。。。