我想将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))
哪一个更好?
答案 0 :(得分:2)
您当前的代码会收到包含文件内容的输入流,但会在将该流写入磁盘上的文件之前将该流的全部内容缓存在byte[]
中。您的“替代1”直接从输入流流式传输到磁盘上的文件,因此内存效率会更高,并且至少与您当前的缓冲方法一样快(可能更快,因为沿途收集的垃圾更少)。
答案 1 :(得分:0)
如果您使用commons-fileupload lib并在流模式下使用 (docs here),您将永远不再需要在内存中保留比您想要的更多的传入文件至。当请求来自客户端并迭代每个项目时,您会为每个表单字段或上传文件获取一个InputStream,并且可以使用该InputStream执行任何操作,例如将其写入文件(并包括抛出异常)如果用户尝试上传,例如,当您的限制为20MB或其他任何情况时上传2GB文件。
使用commons-fleupload的流API的唯一缺点是,处理常规表单字段也必须通过InputStream完成,但这可以通过调用lib的Streams.asString()
轻松完成。