java - Spring Boot 减少大型 CSV 文件的下载时间
问题描述
我有一个用于下载 CSV 文件的 API,该文件的大小可能很大(最大 15MB)。尽管响应时间相当长,但它在 Chrome 中给出了响应。但是,在 Safari 中,它会在 60 秒后显示 504 网关超时。这是代码:
public File dataToCSV(List<String[]> dataLines) throws IOException {
File csvOutputFile = new File("supply_tracker_" + LocalDateTime.now() + ".csv");
try (PrintWriter pw = new PrintWriter(csvOutputFile)) {
dataLines.stream()
.map(data -> String.join(",", data))
.forEach(pw::println);
}
return csvOutputFile;
}
public ResponseEntity<Object> getFile(File csv) throws FileNotFoundException {
if (csv != null) {
InputStreamResource resource = new InputStreamResource(new FileInputStream(csv));
long length = csv.length();
boolean delete = csv.delete();
if (delete) {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", csv.getName()));
return ResponseEntity.ok()
.headers(headers)
.contentLength(length)
.contentType(MediaType.parseMediaType("text/csv"))
.body(resource);
}
} else {
return ResponseEntity.status(HttpStatus.NO_CONTENT).body(null);
}
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
有什么方法可以减少响应时间?另外,是否有临时解决方案可以在 Safari 上进行这项工作?前端在 React 中,API 用于 axios 调用。
解决方案
我建议使用ResponseBodyEmitter
.
您在这里遇到的最大问题是您的客户端必须等待响应准备好 100%,然后服务器才能开始响应。
一旦这段等待时间超过读取超时(通常为 30 秒),您将收到超时错误。增加超时是一个非常短期的解决方案。
使用 ResponseBodyEmitter 允许您的服务器一次写入一行响应,因此初始响应要快得多。
另一个探索的途径是 Spring Reactive 库。我们的应用程序可以在 10、20 分钟内返回许多 GB,而不会出现问题。
推荐阅读
- scala - 如何在 scala 中避免 com.typesafe.config.ConfigException$Missing
- wifi - 如何使用 NL80211_BSS_CAPABILITY 获取扫描网络的 WiFi 安全密钥(WPA、WPA2、ESS)?
- javascript - 在我的文件夹中找不到模块 (discord.js)
- flutter - 如何像 MX Player 那样检测颤动的音频文件夹?
- django-rest-framework - 通过 Celery 任务调用 DRF ViewSet
- php - 数据不通过管理页面中的 ajax 和 jQuery 插入和更新?
- unicode - 如何使用 Arduino IDE 在 Adafruit SSD1306 上显示 Unicode 字符?
- microsoft-graph-api - 从 Exchange 网络服务迁移到 Graph Api
- heroku - 将信用卡添加到 Heroku
- javascript - 如何消除 React js 应用程序中的渲染阻塞资源?