当返回 minio 流作为 spring ResponseEntity 时,如何摆脱 okhttp3 "A connection to ... was was leaked" 警告?

How do I get rid of okhttp3 "A connection to ... was was leaked" warning when returning a minio stream as spring ResponseEntity?

我正在使用 minio 读取一个文件,并且有一个 REST 控制器,returns minio 作为 InputStreamResource 给出的输入流。这是我的代码:

@GetMapping("/download")
fun download(): ResponseEntity<InputStreamResource> {

  // read file from minio
  // getObjectResponse is an InputStream
  ...
  val getObjectResponse = minioClient.getObject(getObjectArgs)

  return ResponseEntity.ok().body(InputStreamResource(getObjectResponse))
}

根据 将 InputStream 包装到 InputStreamResource 中是正确的,并且 spring 应该在传递响应后关闭底层 InputStream。然而我还是得到了臭名昭著的

okhttp3.OkHttpClient: A connection to ... was leaked. Did you forget to close a response body?

我在这里有哪些选择?我宁愿不需要将 minio 内容复制和缓冲到内存中,因为这些文件往往非常大。

只要您关闭 Response、ResponseBody 或像 ResponseBody.inputStream() 这样的流中的任何一个,OkHttp 响应就会被清除。

您依赖于接受您的 InputStreamResource 的调用方才能正确关闭它。

我建议 wrapping/decorating 您传递给 InputStreamResource 的输入流并记录调用何时何地关闭。

通过使用 Yuri Schimkes 的建议来改进日志记录和一些调试,我发现 spring 仅在返回 HTTP 200 时关闭输入流 并且输入流是实际阅读并交付。在我的例子中,有时会发生缓存(spring 使用 etags 的魔法)并且 spring 返回 HTTP 304 而没有消耗和关闭输入流。