尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

百万行 Excel 报表不再卡死:用 Apache Fesod 搞定大文件读写与高性能导出

百万行 Excel 报表不再卡死:用 Apache Fesod 搞定大文件读写与高性能导出 百万行 Excel 报表不再卡死用 Apache Fesod 搞定大文件读写与高性能导出【免费下载链接】fesodFast. Easy. Done. Processing spreadsheets without worrying about large files causing OOM.项目地址: https://gitcode.com/gh_mirrors/fast/fesodApache Fesod 是一款专注处理海量 Excel 的开源 Java 库核心价值是以低内存占用完成大文件的流式读写。去年我接手了公司从 0 到 1 搭建报表导出系统的需求数据量直奔百万行一路踩坑填坑最终把整套方案沉淀下来。这篇文章就用这个真实场景把 Fesod 的用法串起来讲——你不需要一次记太多 API跟着需求走就行。需求一来就是 100 万行老方案为什么扛不住先交代业务背景运营每天要导出一份全量订单明细规模在 80 万到 120 万行之间十来个字段还要带统计汇总。最初用传统 POI 的普通 Workbook 模式开发很快撞上三堵墙内存墙数据全部驻留内存堆外堆内一起爆JVM 频繁 Full GC导出到一半直接 OOM读取墙解析整张表要先整体载入内存百万行场景下基本不可用格式墙一旦要求合并单元格、字体、边框、图片代码量成倍上涨维护成本直线上升。换成 SXSSF 流式写虽然缓解了写入端内存但读取端、样式、合并、图片这些附加题依然要自己造轮子。团队讨论后的结论是与其在 POI 上继续打补丁不如换一个天生为大文件而生的库。选型Apache Fesod 凭什么值得托付Apache Fesod 是 Apache 孵化器下的项目思路继承自成熟的 EasyExcel 体系官方定位就是处理电子表格时不用再担心大文件导致 OOM。它的底层采用 SAX 事件驱动解析xlsx 按 XML 节点逐个流式消费而不是把整张表一次性塞进内存同时内置临时数据缓存策略读到的中间数据可以落盘换空间从机制上绕开了内存瓶颈。判断一个基础库能否长期依赖我通常看三点社区活跃度、文档完整度、是否有人持续维护。Fesod 进入孵化器后迭代稳定官网文档覆盖读取、写入、填充、样式、异常处理等完整主题示例工程里每个功能都有可直接运行的 demo选型阶段这些都是加分项。第一关让 100 万行读进来不 OOM读取端是最先要解决的问题。Fesod 的读取 API 是文件 模型 监听器三段式模型用注解描述列映射监听器负责接收流式吐出的数据行框架不会把结果全部攒在内存里。// 每读到一批数据默认 100 行回调一次边读边消费 FesodSheet.read(orders_2025.xlsx, OrderModel.class, new PageReadListenerOrderModel(page - { orderMapper.batchInsert(page); // 分批入库内存水位始终平稳 })).sheet().doRead();中小文件想一次性拿结果也有doReadAllSync()这类直接返回ListT的入口。针对超大文件ExcelReaderBuilder额外暴露了readCache/readCacheSelector用于定制临时数据的缓存落点属于进阶调优项默认行为已经足够日常使用。第二关报表要好看别手写单元格数据读进来之后下一关是把报表做得像样。Fesod 给好看提供了两条路线。路线一模板填充。业务方经常用 Excel 画好版式标题、汇总行、固定列宽程序只需把变量填进去。模板里写{name}、{number}这类占位符代码侧一个对象或一个 Map 就能完成填充FesodSheet.write(outFile) .withTemplate(templateFile) // 指定版式模板 .sheet() .doFill(fillData); // 也支持 MapString, Object需要控制填充方向的用FillConfig指定垂直/水平方向、是否强制新行、是否自动继承模板样式FillConfig config FillConfig.builder() .direction(WriteDirectionEnum.VERTICAL) .forceNewRow(false) // 默认按需换行兼顾内存 .autoStyle(true) // 自动沿用模板样式 .build();路线二合并与样式。同类数据归并显示是报表刚需注解或策略两种方式任选需要按数据动态决定合并规则的注册一个LoopMergeStrategy即可LoopMergeStrategy merge new LoopMergeStrategy(2, 0); // 每 2 行合并第 0 列 FesodSheet.write(fileName, OrderModel.class) .registerWriteHandler(merge) .sheet() .doWrite(data);字体、边框、背景色、对齐方式等样式能力集中在write/style包下配合注解可以做到模型即样式业务代码里几乎看不到手写 CellStyle 的痕迹。第三关图片和特殊字段也别将就订单报表要带商品图这是当时被 POI 折磨得最狠的点。Fesod 的图片写入支持五种来源字段类型直接决定图片来源无需额外配置public class ProductModel { private File photo; // 本地文件 private byte[] photoBytes; // 内存中的二进制 private URL photoUrl; // 远程图片写入时自动拉取 // InputStream、路径字符串同理 }遇到业务自定义类型比如状态码要转成已支付 / 已发货这种可读文案转换器体系会兜底。实现ConverterT接口的两个方法即可打通读写双向转换注册到全局或字段级别public class StatusConverter implements ConverterInteger { Override public Integer convertToJavaData(ReadConverterContext? context) { // 单元格文本 - 业务值 } Override public WriteCellData? convertToExcelData(WriteConverterContextInteger context) { // 业务值 - 单元格文本 } }上线前的最后一课性能与内存的调优姿势功能跑通之后真正决定系统生死的是性能。这一阶段我们主要做了三件事读侧分批消费用分页监听器控制每批行数避免单次事务过大也避免堆积内存写侧控制水位不要图省事把百万行一次性doWrite按业务批次写多个 sheet 或分多次导出配合流式写入内存曲线始终平稳图片单独规划图片会整体驻留内存量大时优先用 URL 引用而不是内嵌二进制或先压缩再写入。Fesod 官方给出的对比数据是相比传统全量加载方案大文件场景下内存占用能压缩近八成读取速度提升数倍API 的简洁也让代码量明显下降。我们线上实测120 万行导出从经常 OOM、偶发 3 分钟降到稳定 20 秒以内堆内存曲线肉眼可见地平了。从零到一五分钟跑通最小闭环最后给想上手的读者一条最小路径。工程是 Maven 结构先加依赖dependency groupIdorg.apache.fesod/groupId artifactIdfesod-sheet/artifactId version2.0.1/version /dependency再定义一个带注解的模型类读写共用public class OrderModel { ExcelProperty(订单号) private String orderNo; ExcelProperty(金额) private BigDecimal amount; }写入只需一行FesodSheet.write(report.xlsx, OrderModel.class) .sheet(订单明细) .doWrite(orderList);完整可运行的示例在fesod-examples/fesod-sheet-examples目录下quickstart、read、write、fill、web 分类齐全照着跑一遍基本能覆盖日常开发。报表系统上线半年运营再没因为导出问题找过我们。如果你的项目同样被大 Excel 卡死、OOM、导出一团乱困扰不妨克隆仓库https://gitcode.com/gh_mirrors/fast/fesod按这条路径走一遍先把读打通再补样式最后调性能——每一步都有立竿见影的正反馈你会回来感谢自己的。【免费下载链接】fesodFast. Easy. Done. Processing spreadsheets without worrying about large files causing OOM.项目地址: https://gitcode.com/gh_mirrors/fast/fesod创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表