【发布时间】:2021-08-20 09:54:17
【问题描述】:
我有一个简单的 Spring Boot 控制器,它提供 zip 文件,它可以变得相当大。因此,为了不必将整个文件内容加载到内存中,我从要读取的文件中创建了一个 InputStream 并返回一个 StreamingResponseBody,如下所示:
import org.springframework.util.StreamUtils;
@RestController
@RequestMapping("/api/export")
public class ExportController {
@GetMapping(value = "/{fileUuid}")
public StreamingResponseBody exportFile(@PathVariable String fileUuid, HttpServletResponse response) {
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=\"export.zip\"");
InputStream inputStream = new FileInputStream(this.resolveFile(fileUuid));
return outputStream -> {
StreamUtils.copy(inputStream, outputStream); // also tried inputStream.transferTo(outputStream);
};
}
public File resolveFile(String fileUuid) {
// ...
}
}
现在,这对于第一个请求来说效果很好 - 但在那之后,大约 80% 的 请求会返回一个空的响应正文(http-response 只包含响应标头)。我们正在使用JDK11 和Spring Boot 2.4.3。
我在这里做错了什么?
编辑:
奇怪的是,我能够通过将FileInputStream 包装在InputStreamResource 中并返回此资源而不是StreamingResponseBody 来解决此问题:
// ...
var resource = new InputStreamResource(new FileInputStream(this.resolveFile(fileUuid)));
return resource;
但我仍然很好奇原来的方法有什么问题..
【问题讨论】:
-
并没有真正解释为什么它起作用然后又不起作用,但是您是否尝试将 InputStream 完全移动到 lambda 中?另外,您是否同时关闭/刷新 Input 和 OutputStream?对于 Java11,我认为没有理由再使用
StreamUtils.copy,因为有InputStream.transferTo -
是的,尝试摆弄关闭/刷新流,但无济于事。
transferTo似乎也没有解决问题。但是..我能够解决问题,请参阅我的编辑。
标签: java spring spring-boot