提问者:小点点

通过2个rest调用Spring boot流式传输文件


我试图从服务A下载zip文件,在那里它调用服务B文件。我需要一个解决方案来跨服务流文件例如当我调用服务A文件时,它将调用服务B。从这里它应该流到服务A。从服务A它将流到调用者。

服务之间流式传输的原因是,我不想将文件存储在服务A中。我只想传递给调用者而不存储它。

并且让我知道在服务A中使用哪个选项。比如ByteArrayResource或rest模板响应提取器等。

限制服务B不在我的控制范围内,所以到目前为止,我接受文件作为字节数组

@RestController
public class FileUploadController {
  
  @Autowired
  private RestTemplate restTemplate;
  
  // Assume this is from Service A
  @PostMapping(value = "/downloadresource",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
  public ResponseEntity<?> downloadByteResource() throws IOException{
    ByteArrayResource responseObject;
    HttpEntity httpEntity = new HttpEntity<>(new LinkedMultiValueMap<>());
    responseObject= restTemplate.exchange("http://localhost:8080/test", HttpMethod.POST, httpEntity,
        ByteArrayResource.class).getBody();
    
    return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM)
        .header(HttpHeaders.CONTENT_DISPOSITION,
            "attachment; filename=test.zip")
        .body(responseObject);
  }
  // Assume below from service B. which is not in my control
  @PostMapping(value="/test")
  public ResponseEntity<byte[]> test() throws IOException {
    File f = new File("/Users/dummy/Downloads/test.zip");
    byte[] b = Files.readAllBytes(f.toPath());
    return ResponseEntity.ok().contentType(MediaType.APPLICATION_OCTET_STREAM)
        .header(HttpHeaders.CONTENT_DISPOSITION,
            "attachment; filename=" + f.getName())
        .body(b);
  }

}

共1个答案

匿名用户

我想我有一些解决方案,根据visulaVM使用低内存(可视化堆内存)。

请让我知道是否有其他更好的选择。

@PostMapping(value = "/downloadextract",produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
  public ResponseEntity<?> downloadExtract(HttpServletResponse response) throws IOException{
    HttpEntity httpEntity = new HttpEntity<>(new LinkedMultiValueMap<>());
    ResponseExtractor<Object> extractor  = restClient -> {
      StreamUtils.copy(restClient.getBody(), response.getOutputStream());
      return null;
    };
    RequestCallback callback = req -> {
      req.getHeaders().add("auth", "token");
    };
    response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
    response.addHeader(HttpHeaders.CONTENT_DISPOSITION,
        "attachment; filename=test.zip");
    restTemplate.execute("http://localhost:8081/test", HttpMethod.POST, callback,
        extractor);
    return ResponseEntity.ok().build();
  }