You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache POI 3.16生成Excel文件下载后无法正常打开问题求助

Apache POI 3.16生成XLSX文件下载异常解决方案

问题分析与修复

1. XLSX文件无法打开的修复

你提供的XSSF代码中,ContentType设置错误,仍然使用了xls格式的ms-vnd/excel,这会导致浏览器或Office识别文件格式异常。正确的XLSX格式ContentType必须设置为application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,同时需确保响应头的文件名后缀与格式匹配。修复后的代码如下:

Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("sheet1");
Row row = null;
Cell cell = null;
int rowNum = 0;

row = sheet.createRow(rowNum++);
cell = row.createCell(0);
cell.setCellValue("no");

for (int i=0; i<3; i++) {
    row = sheet.createRow(rowNum++);
    cell = row.createCell(0);
    cell.setCellValue(i);
}

// 修正ContentType为XLSX对应的值
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename=example.xlsx");

OutputStream outputStream = response.getOutputStream();
wb.write(outputStream);
// 刷新并关闭流
outputStream.flush();
outputStream.close();
wb.close();

2. 写入ByteArrayOutputStream后样式损坏的修复

你的代码存在两个关键错误:

  • XSSFWorkbook写入流后内部资源会被关闭,第二次调用wb.write(out)会导致文件内容不完整或样式损坏;
  • autoSizeColumns应该在写入流之前执行,写入后Workbook的状态已固化,再调整列宽不会生效。

修复后的代码逻辑应该是:先调整列宽,再将ByteArrayOutputStream的内容写入响应流,而不是重复写入Workbook:

OutputStream out = null;
ByteArrayOutputStream bout = null;

try {
    bout = new ByteArrayOutputStream();
    // 先执行列宽调整
    autoSizeColumns(wb);
    // 只写入一次Workbook到ByteArrayOutputStream
    wb.write(bout);
    
    setHeader(request, response, fileName);
    response.setContentLength(bout.size());
    // 设置正确的ContentType(XLSX格式需对应正确值)
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    
    out = response.getOutputStream();
    // 将ByteArrayOutputStream的内容写入响应流
    bout.writeTo(out);
    out.flush();
    
} catch (Exception e) {
    e.printStackTrace();
} finally {
    try { 
        if (bout != null) bout.close();
        if (out != null) out.close();
        if (wb != null) wb.close();
    } catch (IOException e) { 
        e.printStackTrace(); 
    }
}

结论

这并非Apache POI 3.16的Bug,而是代码中ContentType设置错误、Workbook重复写入流、列宽调整时机错误导致的问题。按照上述方式修复后,XLSX文件即可正常下载并打开,样式也能保持完整。

内容的提问来源于stack exchange,提问作者recadro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:54:33