我有一个API用于下载CSV文件,该文件的大小可能很大(最多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 libs。我们的应用程序可以在10-20分钟内返回许多GB而不会出现问题。
如果这个API是针对最终用户的,与其他API一样,应该考虑其他通信渠道来发送这个文件,如电子邮件或创建文件,上传到某个位置并返回URL而不是文件,这样用户也可以多次下载。