We are building a Spring boot REST endpoint that generates a large XLS file (may contain ~ 1mil lines) and provides it for download. The current solution uses the SXSSF API of Apache POI library for creating the workbook; after that we write the workbook to an output stream, collect the stream in to an array of bytes and then provide this one for download.
How could the content of the workbook be streamed, as we are adding more rows, so that we don't keep the entire file in memory ?
Code for current solution
@RequestMapping(path = "/download/xls", method = RequestMethod.GET, produces = org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<InputStreamResource> downloadXls(HttpServletResponse response, XlsRequest request) throws FileNotFoundException, InternalServerErrorException {
byte[] data = downloadIssuesAsExcel(response, request);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Description", "File Transfer");
headers.add("Content-Disposition", "attachment; filename=justAFile.xlsx");
headers.add("Content-Transfer-Encoding", "binary");
headers.add("Connection", "Keep-Alive");
headers.setContentType(
org.springframework.http.MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
InputStreamResource isr = new InputStreamResource(new ByteArrayInputStream(data));
return ResponseEntity.ok().contentLength(data.length).headers(headers).body(isr);
}
public byte[] downloadIssuesAsExcel(HttpServletResponse response, XlsRequest request)
throws InternalServerErrorException {
try {
SXSSFWorkbook workbook = createExcel(request, response);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
workbook.write(stream);
workbook.dispose();
workbook.close();
stream.close();
return stream.toByteArray();
} catch (Exception e) {
throw new InternalServerErrorException("IO exception while downloading XLS file", e);
}
}
Also tried to write the workbook content directly in the response.getOutputStream() but the file gets corrupted somehow.
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Description", "File Transfer");
response.setHeader("Content-Disposition", "attachment; filename=" + issueDataService.getExcelName(request));
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Connection", "Keep-Alive");
SXSSFWorkbook workbook = createExcel(request, response);
workbook.write(response.getOutputStream());
workbook.dispose();
workbook.close();