Spring将非多部分文件作为流上载

Spring将非多部分文件作为流上载,spring,file-upload,spring-boot,binaryfiles,Spring,File Upload,Spring Boot,Binaryfiles,我正在使用SpringBoot1.2.5,我想将原始二进制文件上传到控制器。文件大小可能很大,因此我不想将整个请求保存在内存中,而是流式传输文件,事实上,文件是在传输开始时生成的,因此客户端甚至不知道文件的大小。我看到了一个如何使用多部分编码的文件上传执行类似操作的示例。然而,我不想要一个多部分编码的上传,只是一个原始的字节流。我似乎找不到在spring中处理此用例的方法。您可以使用HttpServletRequestinputstream。 请注意,如果您有任何过滤器预处理请求并使用input

我正在使用SpringBoot1.2.5,我想将原始二进制文件上传到控制器。文件大小可能很大,因此我不想将整个请求保存在内存中,而是流式传输文件,事实上,文件是在传输开始时生成的,因此客户端甚至不知道文件的大小。我看到了一个如何使用多部分编码的文件上传执行类似操作的示例。然而,我不想要一个多部分编码的上传,只是一个原始的字节流。我似乎找不到在spring中处理此用例的方法。

您可以使用
HttpServletRequest
inputstream。
请注意,如果您有任何过滤器预处理请求并使用inputstream,那么这可能不起作用

@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"));
}

我想和大家分享一些小发现,也许会对大家有所帮助

我使用spring的
MultipartFile
上传大文件,担心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");
}
最后,如果您只想将文件上传到特定的目录/文件,您可以使用此解决方案,它将与手动流式传输文件一样快

重要提示:有两个
transferTo()
方法,一个接收
路径
,另一个接收
文件
。不要使用接收
路径的路径,因为它会复制文件并且速度较慢

EDIT1:

我使用
HttpServletRequest
测试了该解决方案,但它仍将存储一个临时文件,除非您设置spring config
spring.servlet.multipart.enabled=false
。使用
multipathttpservletrequest
的解决方案也是如此

我发现使用我找到的解决方案有三个主要好处:

  • 很简单
  • 它允许您一次处理多个文件,您只需将多个
    @RequestPart MultipartFile
    添加到控制器方法中即可
  • 它允许您轻松处理带有文件的响应主体
  • public ResponseEntity上载文件(@RequestPart@Valid MyCustomPOJO pojo、@RequestPart MultipartFile file1、@RequestPart MultipartFile file2、@RequestPart MultipartFile file3)
    
    以下是我为测试一些概念而创建的测试项目的URL,包括:


    需要澄清的是,在上载过程中调用此处理程序。这意味着没有数据存储在临时文件中,并且在调用时整个文件都不在内存中,对吗?@cmaynard在处理请求头后输入该方法。然后得到请求主体的流。您可能有一个servlet过滤器,它使用类似于
    TeeInputStream
    的东西来保留请求主体的缓冲区,但在默认的spring引导中,SpringMVC项目你不应该有这样的东西。虽然你的研究很有趣,也很有价值,但它与当前关于流式上传/非多方上传的主题无关,谢谢你的回答。我可以使用多部分文件的输入流而不将整个文件保存在任何地方吗?
    @PostMapping("/upload")
    public ResponseEntity<?> uploadFile(@RequestPart MultipartFile file) throws FileNotFoundException, IOException{
    
        file.transferTo(new File("/storage/upload/", file.getOriginalFilename()));
    
        return ResponseEntity.ok("Saved");
    }
    
    public ResponseEntity<?> uploadFile(@RequestPart @Valid MyCustomPOJO pojo, @RequestPart MultipartFile file1, @RequestPart MultipartFile file2, @RequestPart MultipartFile file3)