csv导出必须设置content-type为text/csv; charset=utf-8和content-disposition头,否则浏览器无法识别下载;gin中需手动写header、用csv.newwriter(c.writer)流式写入并调flush(),同时添加utf-8 bom头防excel乱码。

CSV导出必须设置正确的HTTP头
浏览器不会自动识别响应体是CSV,不设对Content-Type和Content-Disposition,下载会失败或变成乱码文件。Gin里得手动写Header,不能只靠c.Data或c.String。
-
Content-Type必须是text/csv; charset=utf-8(不是application/csv,后者部分浏览器不认) -
Content-Disposition推荐用attachment; filename="report.csv",注意文件名不含路径、不带中文(或需URL编码) - 如果用
c.Writer直接写入,记得在写之前调用c.Writer.WriteHeader(200),否则可能被gin默认加header干扰
用encoding/csv写入http.ResponseWriter最稳妥
别把整个CSV内容拼成字符串再c.String——内存占用高,大报表容易OOM;也别用bytes.Buffer中转——多一次拷贝。直接把c.Writer当io.Writer传给csv.NewWriter,边生成边写出。
-
csv.NewWriter(c.Writer)返回的writer需在handler末尾调用.Flush(),否则最后一行可能卡在缓冲区不发出 - 中文字段要确保源数据是UTF-8编码(Go字符串默认就是),无需额外转码;但Excel打开CSV时可能乱码,可在首行前插入BOM:
c.Writer.Write([]byte("\xef\xbb\xbf")) - 字段含逗号、换行符或双引号时,
csv.Writer会自动加引号和转义,不用自己处理
分页数据导出不能直接用API现有分页逻辑
前端请求的page=1&size=20只是看数据,导出要全量。如果DAO层接口只接受offset/limit,得绕过它,或提供无分页的查询方法。
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
- 别在导出接口里循环调用分页查询——N次DB请求+重复JOIN,性能崩盘
- 如果数据量极大(>10万行),考虑加
sql.Rows流式读取 +csv.Writer流式写出,避免全量加载进内存 - 导出过程长时,建议加简单状态提示(如
c.Header("X-Progress", "exporting")),但别依赖它做前端轮询——更可靠的是异步任务+下载链接
文件名动态生成要注意URL编码和兼容性
想让文件名带日期或参数(如user_report_20240520.csv)很常见,但直接拼进Content-Disposition有坑。
- Chrome支持
filename*=UTF-8''xxx.csv格式,但IE只认filename=xxx.csv,稳妥做法是:英文名用filename=,含中文用filename*=并URL编码,同时两个都写(浏览器选它认的那个) - Gin里可这样写:
c.Header("Content-Disposition", `attachment; filename="report.csv"; filename*=UTF-8''` + url.PathEscape("用户报表.csv")) - Windows系统对文件名长度、非法字符(
\ / : * ? " |)敏感,生成前务必过滤
实际导出逻辑里最容易被跳过的,是csv.Writer.Flush()和BOM头——前者导致文件少最后一行,后者导致Excel打不开中文。这两个点没验证过,基本等于没测完。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










