【问题标题】:write large HSSFWorkbook into ServletOutputStream将大型 HSSFWorkbook 写入 ServletOutputStream
【发布时间】:2021-05-05 09:39:56
【问题描述】:

我有以下代码。当我尝试将记录列表导出到具有少量记录(大约 200 条记录)的 Excel 时,这工作正常:

  @Path("/toExcel")
  @GET
    public Response excelCustomersReport(@QueryParam("page") Integer page, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("filter") FilterWrapper filter, @QueryParam("sort") SortWrapper sort) throws Exception {
        response.setContentType("application/octet-stream");
        DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
        String currentDateTime = dateFormatter.format(new Date());
        String headerKey = "Content-Disposition";
        String headerValue = "attachment; filename=report_" + currentDateTime + ".xlsx";
        response.setHeader(headerKey, headerValue);
        HSSFWorkbook workbook=userService.export(page,start,limit,filter,sort);
        ServletOutputStream outputStream=response.getOutputStream();
        workbook.write(outputStream);
        workbook.close();
        outputStream.close();

        return ResponseHelper.ok(response);
    }

当列表变大(前 200 多条记录)时,悲剧就开始了。它给出了以下错误:

 <An I/O error has occurred while writing a response message entity to the container output stream.
org.glassfish.jersey.server.internal.process.MappableException: java.io.IOException: CLOSED

我搜索了很多,最终得到了这个解决方案:

 public Response excelCustomersReport(@QueryParam("page") Integer page, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("filter") FilterWrapper filter, @QueryParam("sort") SortWrapper sort) throws Exception {
        response.setContentType("application/octet-stream");
        DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
        String currentDateTime = dateFormatter.format(new Date());
        String headerKey = "Content-Disposition";
        String headerValue = "attachment; filename=report_" + currentDateTime + ".xlsx";
        response.setHeader(headerKey, headerValue);
        HSSFWorkbook workbook=userService.export(page,start,limit,filter,sort);
        response.setHeader("Content-Length", String.valueOf(workbook.getBytes().length));
        InputStream is=new ByteArrayInputStream(workbook.getBytes());
        ServletOutputStream sos = response.getOutputStream();
        long byteRead = 0;
        try {
            byte[] buf = new byte[1000];
            while (true) {
                int r = is.read(buf);
                if (r == -1)
                    break;
                sos.write(buf, 0, r);
                byteRead +=r;
                if(byteRead > 1024*1024){ //flushes after 1mb
                    byteRead = 0;
                    sos.flush();
                }
            }
        }catch (Exception e) {
           e.printStackTrace();
        }finally{
            if(sos != null){
                sos.flush();
            }
            try{is.close();}catch(Exception e){}
            try{sos.close();}catch(Exception e){}
        }

        return ResponseHelper.ok(response);
    }

冲洗溪流是大多数人指向的唯一方法。现在这个解决方案不仅适用于大数据,也适用于较小的数据(不适用于两种情况)。它给出了这个错误:

An I/O error has occurred while writing a response message entity to the container output stream.
org.glassfish.jersey.server.internal.process.MappableException: com.fasterxml.jackson.databind.JsonMappingException: Direct self-reference leading to cycle 

我尝试使用 XSSFWorkbook 而不是 HSSFWorkbook 。但是 weblogic 甚至没有构建项目并抛出了与 meta-model 相关的错误。

无论如何,这段代码有什么问题。如何将较大的文件写入流?我的 apache poi 版本是 3.11。

【问题讨论】:

标签: jersey jax-rs hssfworkbook


【解决方案1】:

正如 Paul Samsotha 评论的 S.O 链接所说,我应该使用 StreamingOutput 而不是 ServletOutputStream。所以这个方法应该改写成这样:

    @Path("/toExcel")
    @GET
    public Response excelCustomersReport(@QueryParam("page") Integer page, @QueryParam("start") Integer start, @QueryParam("limit") Integer limit, @QueryParam("filter") FilterWrapper filter, @QueryParam("sort") SortWrapper sort) throws Exception {
        response.setContentType("application/octet-stream");
        DateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
        String currentDateTime = dateFormatter.format(new Date());
        String headerKey = "Content-Disposition";
        String headerValue = "attachment; filename=report_" + currentDateTime + ".xlsx";
        response.setHeader(headerKey, headerValue);
        HSSFWorkbook workbook=userService.export(page,start,limit,filter,sort);
        StreamingOutput output = new StreamingOutput() {
            @Override
            public void write(OutputStream out)
                    throws IOException, WebApplicationException {
                workbook.write(out);
                out.flush();
            }
        };
        return Response.ok(output)
                .build();
    }

【讨论】:

    猜你喜欢
    • 2022-09-30
    • 2022-01-05
    • 2013-08-21
    • 2015-06-30
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 1970-01-01
    相关资源
    最近更新 更多