Java 将POI SXSSFWorkbook流式传输到servlet输出流

Java 将POI SXSSFWorkbook流式传输到servlet输出流,java,excel,servlets,spring-restcontroller,apache-poi-4,Java,Excel,Servlets,Spring Restcontroller,Apache Poi 4,我们正在构建一个Spring引导REST端点,它生成一个大的XLS文件(可能包含~1mil行),并提供下载。 当前解决方案使用ApachePOI库的SXSSFAPI创建工作簿; 之后,我们将工作簿写入一个输出流,将该流收集到一个字节数组中,然后提供这个字节供下载 当我们添加更多行时,工作簿的内容如何流式传输,这样我们就不会将整个文件保存在内存中 当前解决方案的代码 @RequestMapping(path = "/download/xls", method = RequestMethod.GET

我们正在构建一个Spring引导REST端点,它生成一个大的XLS文件(可能包含~1mil行),并提供下载。 当前解决方案使用ApachePOI库的SXSSFAPI创建工作簿; 之后,我们将工作簿写入一个输出流,将该流收集到一个字节数组中,然后提供这个字节供下载

当我们添加更多行时,工作簿的内容如何流式传输,这样我们就不会将整个文件保存在内存中

当前解决方案的代码

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

我刚刚使用了您的代码作为模板,并创建了运行良好的控制器

@RestController
公共类XLSX控制器{
@RequestMapping(path=“/download/xls”,method=RequestMethod.GET,products=“application/vnd.openxmlformats officedocument.spreadsheetml.sheet”)
public void downloadXls(HttpServletResponse r)引发IOException{
r、 setHeader(“内容描述”、“文件传输”);
r、 setHeader(“内容处置”、“附件;文件名=justAFile.xlsx”);
r、 setHeader(“内容传输编码”、“二进制”);
r、 setHeader(“连接”、“保持活动”);
试试(SXSSFWorkbook w=getWorkbook()){
w、 写入(r.getOutputStream());
}
}
具有100万行的工作簿的重量超过40 Mb

org.springframework:spring-webmvc:5.2.2.RELEASE
org.apache.poi:poi-ooxml:4.1.1

这个答案有用吗?我使用了对servlet输出流的直接写入,它工作得很好。您能展示
response.getOutputStream()的代码吗
case?可能有多种原因,例如是否指定了内容长度?Hi@Smile,感谢您的想法。如果我们决定先将整个文件保存在磁盘上,这将是一种有效的方法。我仍然希望找到一种直接从内存中流式传输的方法。Hi@edwgiz,我实际上并没有添加内容长度头呃,我认为这意味着首先要访问整个文件。我用
response.getOutputStream()的代码片段更新了我的问题
。您是否发现与您的版本不同的东西,可能会篡改文件?是的,这很有效。我实际上在创建工作簿的方法上遇到了一些问题,并且在尝试写入输出流时,这些问题会随机出现。感谢@edwgiz确认解决方案!
org.springframework:spring-webmvc:5.2.2.RELEASE
org.apache.poi:poi-ooxml:4.1.1