InputStream 在 spring 控制器中关闭

Nik*_*las 2 java stream try-with-resources spring-restcontroller

使用 spring 控制器,端点在主体响应中返回文件。我想确保不要使用“尝试使用资源”来避免资源泄漏,但在邮递员中我会收到错误:

“错误”:“内部服务器错误”,“消息”:“流已关闭”,

Spring控制器中的代码片段:

InputStreamResource result;
ResponseEntity<Resource> response;
try(FileInputStream ios = new FileInputStream(file)){
    result = new InputStreamResource(ios);
    response = ResponseEntity.ok()
        .headers(/*some headers here*/)
        .contentLength(file.length())
        .contentType(/*some media type here*/)
        .body(result);
    logger.info("successfully created");
    return response;
} catch (IOException e) {
        //some code here..
}
Run Code Online (Sandbox Code Playgroud)

有趣的是,在日志中我收到了成功消息,但在邮递员或浏览器中(这是一个 GET 请求)我收到了错误。

如果不使用“try-with-resource”,它会起作用,但我担心这种方式会导致资源泄漏。

LHC*_*HIN 6

因为try with resources会调用close()before return,所以会出现“Stream Closed”错误。
一个简单的方法是直接将 的实例放入InputStreamResourcein 中.body(),网络上的大多数示例也是这样做的。但是,我不确定是否会正确关闭资源以防止应用程序资源泄漏。

response = ResponseEntity.ok()
    .contentLength(file.length())
    .body(new InputStreamResource(new FileInputStream(file)));
return response;
Run Code Online (Sandbox Code Playgroud)

另一种方式,如果您想流式传输响应,可以使用StreamingResponseBody.

StreamingResponseBody接口 (引自Spring网站)

这是一个函数式接口,因此可以用作 lambda 表达式或方法引用的赋值目标。

示例代码:

StreamingResponseBody responseBody = outputStream -> {
    Files.copy(file.toPath(), outputStream);
};

response.ok()
    .contentLength(file.length())
    .body(responseBody);
return response;
Run Code Online (Sandbox Code Playgroud)

  • 我想`ResourceHttpMessageConverter`关闭流:/sf/ask/3406200801/#48660203 (4认同)