cma*_*ard 11 spring file-upload binaryfiles spring-boot
我正在使用 Spring Boot 1.2.5,我想将原始二进制文件上传到控制器。文件大小可能很大,所以我不想将整个请求保存在内存中,而是流式传输文件,实际上文件是在传输开始时生成的,因此客户端甚至不知道文件的大小。我在此处看到了一个示例,说明如何使用多部分编码文件上传执行类似操作。但是,我不想要分段编码的上传,只需要原始字节流。我似乎找不到在春季处理这个用例的方法。
您可以只使用输入HttpServletRequest
流。
请注意,如果您有任何过滤器来预处理请求并使用输入流,那么这可能不起作用。
@ResponseBody
@RequestMapping(path="fileupload", method = RequestMethod.POST, consumes = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void fileUpload(HttpServletRequest request) throws IOException {
Files.copy(request.getInputStream(), Paths.get("myfilename"));
}
Run Code Online (Sandbox Code Playgroud)
我想分享一些可能对某人有所帮助的小发现。
我正在使用 springMultipartFile
上传大文件,并担心 spring 会将内容存储在内存中。因此,我决定使用该getInputStream()
方法,希望这可以将文件直接流式传输到所需位置:
@PostMapping("/upload")
public ResponseEntity<?> uploadFile(@RequestPart MultipartFile file) throws FileNotFoundException, IOException{
FileCopyUtils.copy(file.getInputStream(), new FileOutputStream(new File("/storage/upload/", file.getOriginalFilename())));
return ResponseEntity.ok("Saved");
}
Run Code Online (Sandbox Code Playgroud)
当我使用 2GB 文件测试控制器时,需要很长时间才能命中控制器方法。于是调试了一下,发现spring/Tomcat先把文件存放在一个临时文件夹中,然后再处理给控制器。这意味着,当您调用getInputStream()
它时,它会返回FileInputStream
指向存储在文件系统上的文件,而不是直接从客户端浏览器流式传输。
换句话说,调用FileCopyUtils.copy()
很慢,因为它将整个文件复制到另一个位置,然后删除临时文件,使得完成请求需要两倍的时间。
我调查并发现您可以禁用 spring 功能并手动处理多部分请求,但有点复杂且容易出错。所以,再挖掘一点,我发现MultipartFile
有一个方法被调用transferTo
,实际上将临时文件移动到所需的位置。我测试了它,它是即时的。我的代码是这样的:
@PostMapping("/upload")
public ResponseEntity<?> uploadFile(@RequestPart MultipartFile file) throws FileNotFoundException, IOException{
file.transferTo(new File("/storage/upload/", file.getOriginalFilename()));
return ResponseEntity.ok("Saved");
}
Run Code Online (Sandbox Code Playgroud)
结论,如果您只想将文件上传到特定目录/文件,您可以使用此解决方案,它与手动流式传输文件一样快。
重要提示:有两种transferTo()
方法,一种接收 a Path
,另一种接收File
. 不要使用接收 a 的那个,Path
因为它会复制文件并且速度很慢。
编辑1:
我使用 测试了该解决方案HttpServletRequest
,但除非您设置 spring config ,否则它仍将存储一个临时文件spring.servlet.multipart.enabled = false
。使用 的解决方案也会发生同样的情况MultipartHttpServletRequest
。
使用我发现的解决方案,我看到了三个主要好处:
@RequestPart MultipartFile
在控制器方法中添加多个文件public ResponseEntity<?> uploadFile(@RequestPart @Valid MyCustomPOJO pojo, @RequestPart MultipartFile file1, @RequestPart MultipartFile file2, @RequestPart MultipartFile file3)
Run Code Online (Sandbox Code Playgroud)
这是我为测试一些概念而创建的测试项目的 URL,包括这个:
https://github.com/noschang/SpringTester
归档时间: |
|
查看次数: |
8156 次 |
最近记录: |