java - 为什么当我开始读取时,InputStreamResource 会关闭?

标签 java mongodb spring-mvc

我有一个 MongoDB,它存储一个 csv 文件和两个微服务(Spring Boot 应用程序)。一个微服务处理文件上传并支持以流的形式获取这些文件。其他微服务处理文件。这些微服务是分开的,因为我稍后可能想以不同于 MongoDB 的方式存储文件,并且我不想由此影响其他服务。

我的问题是,当文件服务将文件作为 InputStreamResource 返回时,如下所示:

@RequestMapping(value = "/upload/{importId}", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<InputStreamResource> getUploadedFile(@PathVariable("importId") String importId)
        throws ImportFileNotFoundException {
    GridFSDBFile file = FileImportClient.getInstance().getFile(importId);

    return ResponseEntity
            .ok()
            .contentLength(file.getLength())
            .body(new InputStreamResource(file.getInputStream()));
}

我想从已经关闭的流中读取数据。

ResponseEntity<InputStreamResource> response = restTemplate
            .getForEntity("http://upload-service/upload/" + importId, InputStreamResource.class);
BufferedReader fileReader = new BufferedReader(new InputStreamReader(response.getBody().getInputStream()));
for (CSVRecord record : CSVFormat.DEFAULT.parse(fileReader)) {/*toStuff()*/}

我得到了 java.io.IOException: Stream closed由parse方法引起的。

如果我只是curl localhost:<port>/upload/<importId>我得到了整个 csv 文件。 有谁知道为什么输入流被关闭以及如何解决这个问题?

堆栈跟踪:

java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:170)
at java.io.BufferedInputStream.read(BufferedInputStream.java:336)
at java.io.FilterInputStream.read(FilterInputStream.java:133)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.read1(BufferedReader.java:210)
at java.io.BufferedReader.read(BufferedReader.java:286)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.read(BufferedReader.java:182)
at org.apache.commons.csv.ExtendedBufferedReader.read(ExtendedBufferedReader.java:60)
at org.apache.commons.csv.Lexer.nextToken(Lexer.java:89)
at org.apache.commons.csv.CSVParser.nextRecord(CSVParser.java:498)
at org.apache.commons.csv.CSVParser$1.getNextRecord(CSVParser.java:439)
at org.apache.commons.csv.CSVParser$1.hasNext(CSVParser.java:452)
at <mypackage>.<myclass>.process(<myclass>.java:71)

最佳答案

我通过这个链接找到了解决方案:https://jira.spring.io/browse/SPR-7357

[This answers my question] Note that you cannot simply return the InputStream from the extractor, because by the time the execute method returns, the underlying connection and stream are already closed

[This fixes the problem] You can already read an InputStream by using the execute() method on the RestTemplate in combination with a ResponseExtractor implementation

我尝试使用 ResponseExtractor,现在它可以工作了。它看起来像这样:

return restTemplate.execute(new URI("http://<myservice>/upload/" + importId), HttpMethod.GET, null,
            new ResponseExtractor<MyObject>() {
                @Override
                public MyObject extractData(ClientHttpResponse response) throws IOException {
                    CSVParser parse = CSVFormat.DEFAULT.parse(new BufferedReader(new InputStreamReader(response.getBody())));
                    for (CSVRecord record : parse) {/*dostuff*/}
                    return new MyObject();
                }
            });

关于java - 为什么当我开始读取时,InputStreamResource 会关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35292207/

相关文章:

java - Spring MVC 异步方法 (RXJava)

java - jar 和类路径通配符

java - Android Studio 如果输入为 Decimal 应用程序崩溃

java - java中的日期格式

mongodb - "fire and forget"在 MongoDB 中写入的确切含义是什么

spring - 在 weblogic 10.3.6 中部署 Spring 4.1.6 mvc webapp

java - Spring Security - permitAll() 不允许未经身份验证的访问

java - 以多态方式将 Java 枚举值转换为字符串列表

javascript - meteor 应用: Error invoking Method 'saveProject' : Internal server error [500]

mongodb - 分页时根据唯一字段mongodb获取数据