java - InputStream 在 spring Controller 中关闭

标签 java stream spring-restcontroller try-with-resources

使用 spring Controller ,端点在正文响应中返回文件。 我想确保不要使用“尝试使用资源”来避免资源泄漏,但在 postman 中我会收到错误:

"error": "Internal Server Error", "message": "Stream Closed",

Spring Controller 中的代码片段:

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..
}

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

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

最佳答案

因为尝试使用资源会在返回之前调用close(),所以会发生“Stream Closed”错误。
一个简单的方法是直接将InputStreamResource的实例放在.body()中,网上的大多数示例也是这样做的。但是,我不确定是否会正确关闭资源以防止应用程序资源泄漏。

response = ResponseEntity.ok()
    .contentLength(file.length())
    .body(new InputStreamResource(new FileInputStream(file)));
return response;

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

Interface StreamingResponseBody (quoted from Spring website)

This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

示例代码:

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

response.ok()
    .contentLength(file.length())
    .body(responseBody);
return response;

关于java - InputStream 在 spring Controller 中关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58079500/

相关文章:

java - Gradle 构建过程中使用了哪个已安装的 JDK

java - 在 Eclipse 中使用 Git 会导致很多错误

java - 如何使用正则表达式匹配某类词前的所有内容

java - Struts2 链接打开文件仅适用于 IE

c# - ASP.NET Web API StreamContent - 让浏览器显示下载进度

spring - 内容类型 'text/plain;charset=UTF-8' 在 RestController 类中的 Spring Boot 中不支持错误

angular - 如何将 csrf token 添加到 Angular 2 应用程序

java - @运行时的值

c - c 中的两个流相互干扰

java - Spring Jackson 数组而不是 List