简体   繁体   中英

Spring Boot reduce download time of large CSV file

I have an API for downloading a CSV file which can be huge in size(up to 15MB). Although the response time is pretty high, it is giving a response in Chrome. However, in Safari, it shows 504 Gateway timeout after 60 secs. Here is the code for that:

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);
}

What are the ways to reduce the response time? Also, is there a temporary solution to make this work on Safari? The front-end is in React and the API works on axios calls.

I'd suggest using a ResponseBodyEmitter .

The big problem you have here is your client has to wait for the response to be 100% prepared before the server can start to respond.

Once this period of waiting exceeds the read timeout (usually 30s) you will get timeout errors. Upping the timeout is a very short term solution.

Using the ResponseBodyEmitter allows your server to write the response a line at a time so the initial response is much sooner.

Another avenue to explore would be the Spring Reactive libs. We have apps that return many GB over 10, 20 minutes without issue.

如果此 API 用于与其他 API 类似的最终用户,则应考虑其他通信渠道来发送此文件,例如电子邮件或创建文件,上传到某个位置并返回 URL 而不是文件,这样用户也可以多次下载它.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM