微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决通过 2 个 rest 调用 spring boot 流式传输文件

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

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

还要让我知道在服务 A 中使用哪个选项。例如 ByteArrayResource 或休息模板响应提取器等。

限制服务 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);
  }

}

解决方法

我想我得到了一些根据 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();
  }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。