Revel 框架无内置 Excel 导出能力,需选用 github.com/xuri/excelize/v2 库流式写入,设正确响应头、显式中文字体、避免全量加载数据,并通过 Flush 主动刷缓冲防卡死。

Revel 框架本身不内置 Excel 导出能力,也没有官方推荐的 Excel 库。你要导出 Excel,得自己选库、配流式写入逻辑、处理 HTTP 响应头,否则容易卡死、乱码或内存爆掉。
Revel 里用 github.com/xuri/excelize/v2 写 Excel 文件
这是目前 Go 生态最活跃、文档最全、支持 XLSX 的纯 Go 库,不依赖 CGO,适合嵌入 Web 服务。它比老版 tealeg/xlsx 更稳定,也比 go-excel 功能更全。
- 别用
excelize的Save直接写磁盘再读取返回——会多一次 IO,且并发下文件名冲突风险高 - 必须用
f.Write把内容直接写进http.ResponseWriter,配合Content-Disposition头触发下载 - 中文表头要显式设字体:
style := f.NewStyle(&excelize.Style{Font: &excelize.Font{Name: "微软雅黑", Size: 11}}),否则默认是无中文字体的 Calibri - 如果导出数据量超 5 万行,记得调用
f.SetRowHeight前先批量设置样式,避免每行都新建 Style 对象——excelize的 Style 是引用计数管理,但高频 NewStyle 仍会拖慢速度
Revel Action 里怎么返回 Excel 流而不超时
Revel 默认 action 超时是 60 秒,导出 10 万行以上很容易触发。不能靠改全局 timeout,得让导出走异步 + 状态轮询,或者至少把响应流控住。
诊断并修复涉及公式、命名范围、Power Query 刷新、数据透视表、VBA/宏保存等问题的 Microsoft Excel XLSX 工作簿
- 在
Controller方法开头加c.Response.Out.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") - 紧接着设下载头:
c.Response.Out.Header().Set("Content-Disposition", `attachment; filename="report.xlsx"`) - 用
defer c.Response.Out.Close()防止连接未释放;但注意 Revel 的Out是ResponseWriter,不是io.WriteCloser,所以实际要用c.Response.Out.(http.Flusher).Flush()主动刷缓冲 - 若数据来自数据库,务必用
sql.Rows流式扫描,而不是db.Find(&list)全量加载——后者在 Revel 的 controller 里会把整张表塞进内存,GC 来不及回收
为什么不用 github.com/360EntSecGroup-Skylar/excelize 旧版
这个路径是旧版库的 GitHub 地址,现已归档,v2 版本迁移到了 xuri/excelize。继续用旧版会遇到几个硬伤:
- 对合并单元格(
MergeCell)的支持有 bug,导出后 Excel 打开报“发现不可读内容” - 不支持条件格式(Conditional Formatting),而财务类报表常需要红绿底色标异常值
- 没有
AutoFilterAPI,无法给表头加筛选下拉箭头 - v1 的
SetCellValue在并发写同一文件时可能 panic,v2 已修复并加了锁保护
真正难的不是“怎么写进 Excel”,而是“怎么让 Revel 不拦着你写”。它默认把 response 当作文本流处理,一旦你中途没 flush、没设对 header、没控制好内存分配节奏,就会静默失败或卡在 loading。导出逻辑越靠近底层 IO,越要盯紧那几行 Write 和 Flush 的位置。

















