如何正确实现 Excel 文件的分块生成与传输

风瑶姑娘_8596

风瑶姑娘_8596

2026-08-08

840人浏览

原创

如何正确实现 Excel 文件的分块生成与传输

本文详解如何避免 sxssfworkbook 分块写入时因重复创建同名 sheet 导致数据截断的问题,提供基于内存流的增量写入方案,并对比二进制分块传输的适用场景。

本文详解如何避免 sxssfworkbook 分块写入时因重复创建同名 sheet 导致数据截断的问题,提供基于内存流的增量写入方案,并对比二进制分块传输的适用场景。

在使用 Apache POI 生成大型 Excel 文件时,常见误区是试图通过循环调用 workbook.write(outputStream) 多次向同一 ServletOutputStream 写入多个独立工作表(如反复 workbook.createSheet("Datos")),这会导致严重问题:

  • SXSSFWorkbook 不支持对已写入流的 workbook 二次写入;
  • 重复创建同名 sheet 会抛出 IllegalArgumentException: The sheet name "Datos" is already in use;
  • 即使强制新建 sheet,旧 sheet 数据不会自动合并,且 workbook.write() 每次都会重写整个流起始位置,造成覆盖而非追加。

✅ 正确做法是:单 sheet 增量构建 + 一次性写入,而非分多次写流。以下是推荐实现:

✅ 推荐方案:增量构建后一次性写出

@Override
public void generateAndSendExcelChunks(ServletOutputStream outputStream) throws IOException {
    // 使用 SXSSFWorkbook 启用流式写入(避免 OOM)
    try (SXSSFWorkbook workbook = new SXSSFWorkbook(100)) {
        Sheet sheet = workbook.createSheet("Datos");

        int totalRows = 10000;
        int rowsPerChunk = 100;

        // 分批生成行,但全部写入同一 sheet
        for (int currentRow = 0; currentRow <blockquote>
<p>⚠️ 注意事项:  </p><div class="aritcle_card flexRow artxards">
											<div class="artcardd flexRow">
												<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3983" title="Excel工具(专业版)"><img
														src="https://img.php.cn/upload/skill/000/000/081/178988056932244.jpg" alt="Excel工具(专业版)" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
												<div class="aritcle_card_info flexColumn">
													<a rel="nofollow" href="/xiazai/skill3983" title="Excel工具(专业版)" class="overflowclass">Excel工具(专业版)</a>
													<p class="overflowclass">Excel 全能力版:多表合并、透视表、图表、大数据处理、自动化流水线与数据库联动。</p>
												</div>
												<a rel="nofollow" href="/xiazai/skill3983" title="Excel工具(专业版)" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
												</a>
											</div>
										</div>
<ul>
<li>SXSSFWorkbook 的构造参数(如 100)表示内存中保留的行数,其余自动刷盘到临时文件,大幅降低内存占用;  </li>
<li>
<strong>绝不可在循环内调用 workbook.write()</strong> —— 它会将当前 workbook 状态完整写入流,后续再写即覆盖而非追加;  </li>
<li>若需真正“分块响应”(如 HTTP 流式传输给前端),应改用 Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + Transfer-Encoding: chunked,但底层仍需一次性生成完整文件流。</li>
</ul>
</blockquote><h3>❌ 为何二进制分块方案不适用于本场景?</h3><p>提供的答案中给出的 ExcelSplitter / ExcelReconstructor 方案本质是将 Excel 文件视为纯二进制流切割(类似 split -b 1K input.xlsx),其问题在于:  </p>
  • Excel 是 ZIP 容器格式(含 XML、rels、media 等结构化目录),直接按字节切分会破坏内部 ZIP 结构,导致重建后文件损坏或无法打开;
  • DataOutputStream.write(cell.toString().getBytes()) 仅提取文本,丢失公式、样式、数字格式、日期类型等关键元数据;
  • 接收端拼接的只是原始字节,无法还原为合法 .xlsx 文件。

该方案仅适用于纯文本导出场景(如 CSV 分块),或作为自定义协议下的原始数据传输,不能替代真正的 Excel 构建逻辑

✅ 总结

场景 推荐方式 关键点
服务端生成大 Excel 并响应下载 SXSSFWorkbook + 单次 write() 控制内存(rowAccessWindowSize),避免重复写流
需实时进度反馈或超大文件(>100MB) 先生成临时文件 → 分块读取 FileInputStream → ServletOutputStream.write(byte[], off, len) 利用操作系统缓存,不依赖 POI
前后端协作分块上传/下载(非 Excel 特定) 自定义协议 + 校验和(如 SHA-256)+ 块序号命名(file_part_001.bin) 与 Excel 格式解耦,由接收方组装后再解析

始终牢记:Excel 的结构完整性必须由 POI 在写入前保障,而非靠字节拼接恢复。 正确使用 SXSSFWorkbook 的流式能力,才是处理万行级 Excel 的可靠之道。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

excel

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
excel对比两列数据异同
excel对比两列数据异同

Excel作为数据的小型载体,在日常工作中经常会遇到需要核对两列数据的情况,本专题为大家提供excel对比两列数据异同相关的文章,大家可以免费体验。

2023.07.25

4421

7

excel重复项筛选标色
excel重复项筛选标色

excel的重复项筛选标色功能使我们能够快速找到和处理数据中的重复值。本专题为大家提供excel重复项筛选标色的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.31

2656

5

excel复制表格怎么复制出来和原来一样大
excel复制表格怎么复制出来和原来一样大

本专题为大家带来excel复制表格怎么复制出来和原来一样大相关文章,帮助大家解决问题。

2023.08.02

2460

3

excel表格斜线一分为二
excel表格斜线一分为二

在Excel表格中,我们可以使用斜线将单元格一分为二。本专题为大家带来excel表格斜线一分为二怎么弄的相关文章,希望可以帮到大家。

2023.08.02

1424

3

excel斜线表头一分为二
excel斜线表头一分为二

excel斜线表头一分为二的方法有使用合并单元格功能方法、使用文本框功能方法、使用自定义格式方法。本专题为大家提供excel斜线表头一分为二相关的各种文章、以及下载和课程。

2023.08.02

657

5

绝对引用的输入方法
绝对引用的输入方法

绝对引用允许在公式中引用一个固定的单元格,而不会随着公式的复制和粘贴而改变引用的单元格。本专题为大家提供绝对引用相关内容的文章,大家可以免费体验。

2023.08.09

5108

7

java导出excel
java导出excel

在Java中,我们可以使用Apache POI库来导出Excel文件。本专题提供java导出excel的相关文章,大家可以免费体验。

2023.08.18

5723

6

excel输入值非法
excel输入值非法

在Excel中,当输入的数值非法时,有以下多种处理方法。本专题为大家提供excel输入值非法的相关文章,大家可以免费体验。

2023.08.18

1541

3

excel生成二维码
excel生成二维码

虽然Excel本身并不直接支持生成二维码,但我们可以借助一些插件或宏来实现在Excel中生成二维码的功能。本专题为大家提供excel生成二维码的相关文章。

2023.08.18

2338

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Excel 教程
Excel 教程

共162课时 | 43.1万人学习

成为PHP架构师-自制PHP框架
成为PHP架构师-自制PHP框架

共28课时 | 3.5万人学习