fputcsv() 写 csv 需先 fopen('w'),再写标题行和数据行;导出下载须设 content-type 与 content-disposition 头且无前置输出;加 utf-8 bom 解决 excel 中文乱码;大数据应边查边写防内存溢出。

用 fputcsv() 写入带标题行的 CSV 文件
PHP 原生支持 CSV 生成,核心是 fputcsv() 函数,它自动处理字段分隔、引号包裹和特殊字符转义。关键不是“手动拼字符串”,而是用文件句柄逐行写入,包括标题行。
常见错误是把标题当普通数据写、漏掉 fopen() 的 'w' 模式、或没设置 header() 导致浏览器直接显示乱码。
- 先用
fopen($filename, 'w')创建可写文件(注意权限) - 用
fputcsv($fp, $header_array)写标题行,例如['姓名', '邮箱', '注册时间'] - 循环数据,对每条记录调用
fputcsv($fp, $row),数组键名不会被写入,只写值 - 写完必须
fclose($fp),否则内容可能未刷入磁盘
导出到浏览器下载而非保存在服务器
如果目标是让用户点击下载 CSV,就不能只写文件,得配合 HTTP 头。重点在于 Content-Type 和 Content-Disposition 的组合,且必须在任何输出前调用。
容易踩的坑:开头有空格、BOM 字节、echo 或 print 提前触发输出,导致 header 报错 “headers already sent”。
立即学习“PHP免费学习笔记(深入)”;
- 用
ob_end_clean()清除已有的输出缓冲(谨慎使用,确认无前置输出) - 设置
header('Content-Type: text/csv; charset=utf-8') - 设置
header('Content-Disposition: attachment; filename="data.csv"') - 用
php://output替代文件路径:$fp = fopen('php://output', 'w') - 写入完成后不需
fclose(),系统自动关闭
中文乱码问题:UTF-8 BOM 是必要手段
Excel 默认用系统编码打开 CSV,Windows 上常识别为 ANSI,导致中文变问号。加 UTF-8 BOM(\xEF\xBB\xBF)是兼容性最强的解法,不是“多此一举”。
别用 mb_convert_encoding() 强转编码——原始数据已是 UTF-8,问题出在 Excel 缺少编码提示。
- 在写入标题前,先用
fwrite($fp, "\xEF\xBB\xBF") - 确保所有字段值是 UTF-8 编码(从数据库查出时就应是,如 MySQL 连接设
utf8mb4) - 避免用
iconv('GBK', 'UTF-8', $str)处理字段——除非你确定源数据是 GBK
大数据量导出时避免内存溢出
一次性把几万行读进 PHP 数组再循环写入,极易触发 Allowed memory size exhausted。正确做法是边查边写,用游标式查询或分页流式读取。
MySQL 中用 SELECT ... INTO OUTFILE 虽快,但依赖服务器权限且不灵活;PHP 层控制更安全、可加逻辑。
- 用
PDO::FETCH_ASSOC+while ($row = $stmt->fetch())逐行获取 - 每写 1000 行执行一次
ob_flush()和flush()(仅限输出到浏览器场景) - 禁用
set_time_limit(0)防止超时中断(但要评估真实需求,非必需) - 不要用
file_put_contents()拼接整块 CSV 字符串——这是内存杀手











