java - 需要分块下载大文件
问题描述
我有 20 MB 的文件。我只想在浏览器中以块/流的形式下载文件,这样如果有另一个请求,它不会被长时间阻塞。
我还在长文件中看到了暂停行为。现在不需要它。如果有人可以解释这一点,因为我很想知道它是如何工作的。
我将文件保存在数据库中。当我收到下载文件的请求时。我将从数据库中获取文件。我将字节码推送到响应正文中并将其发送到浏览器。在浏览器中,我创建了一个链接并一次性下载文件。
后端代码:
@GetMapping("/job-detail/{jobExecutionId}/file-detail")
public ResponseEntity<Resource> getFileDetail(@PathVariable final Long jobExecutionId) {
final FileDetailDto fileDetailDto =
fileTaskletService.getFileDetailByExecutionId(jobExecutionId);
return ResponseEntity.ok().contentType(new MediaType("text", "csv"))
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileDetailDto.getFileName() + "\"")
.body(new ByteArrayResource(fileDetailDto.getData()));
}
我想分块下载文件,以便其他请求也可以同时开始下载。
解决方案
从您的问题的措辞听起来您希望服务器框架为您设置以下标头,以便数据以分块的形式流回:
Transfer-Encoding: chunked
为此,您需要提供一个预先不知道完整大小的 Spring 资源。您已经使用ByteArrayResource
了已知完整大小并导致在Content-Length
响应中设置标头并且不使用分块的地方。
更改要使用的代码,InputStreamResource
服务将使用分块传输编码和无内容长度将响应流式传输回客户端。这是一个示例(未选中语法):
try(ByteArrayInputStream bis = new ByteArrayInputStream(fileDetailDto.getData())) {
return ResponseEntity.ok().contentType(new MediaType("text", "csv"))
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + fileDetailDto.getFileName() + "\"")
.body(new InputStreamResource(bis));
}
虽然这会给你一个分块的响应,但我不相信这是你浏览器问题的根源,因为无论服务器如何提供数据,它们都非常有能力异步流回数据。
推荐阅读
- wpf - 隐式样式(仍然)不适用于 SciChart WPF
- mysql - SQL 查询中的列数
- amazon-web-services - 如何为 AWS 备份虚拟 MFA
- angular - 在 mat-table 父级中使用 ngif 时,mat-filtering/mat-sort 无法正常工作
- r - 在R中的组内绑定行
- javascript - 在显示/隐藏时使用多个 div
- java - Java 核心转储了 safepoint.cpp:310 错误
- json - 从 google protobuff 对象中提取数据的正确方法是什么?
- bash - 提取 rpm 包并将输出分配给变量
- javascript - 在 react.js 中使用 ref 显示/隐藏多个按钮