php查询数据怎么导出csv_查询结果转csv文件保存【操作】


PHP导出CSV需用fputcsv流式处理并加UTF-8 BOM:清空缓冲、设置header、写BOM、逐行fetch,避免内存溢出与Excel乱码。

PHP 查询 MySQL 后直接输出 CSV 文件(浏览器下载)

最常用场景:后台导出报表,用户点击即下载。关键不是“保存到服务器”,而是让浏览器弹出下载对话框。

核心要点:fputcsv() 是 PHP 原生安全写 CSV 的函数,别用字符串拼接;输出前必须清空缓冲区、设置正确 header;MySQL 查询结果需转为二维数组(每行是 array)。

  • 务必在 header() 之前没有输出(包括空格、BOM、echovar_dump
  • 使用 ob_end_clean() 清除可能存在的前置输出
  • 文件名中的中文要用 rawurlencode() 处理,否则 IE/Edge 可能乱码
  • fputcsv() 自动处理字段内含逗号、换行、双引号的情况,比手动 str_replace 可靠得多
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="user_export_' . rawurlencode(date('Y-m-d')) . '.csv"');
header('Cache-Control: no-cache');

$output = fopen('php://output', 'w');
fputcsv($output, ['ID', '用户名', '邮箱', '注册时间']); // 表头

$stmt = $pdo->query("SELECT id, username, email, created_at FROM users WHERE status = 1");
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
    fputcsv($output, $row);
}
fclose($output);

导出大表时内存溢出怎么办(超 10 万行)

fetchAll() 把全部数据读进内存,PHP 很容易报 Fatal error: Allowed memory size exhausted。必须流式处理(streaming)。

  • 禁用 PDO 的默认缓存行为:$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false)
  • fetch() 逐行取,而不是 fetchAll()
  • 每写 1000 行调用一次 ob_flush() + flush(),防止 Web 服务器缓冲卡住
  • 避免在循环里做耗时操作(如格式化日期、查关联表),提前在 SQL 中处理好
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$stmt = $pdo->prepare("SELECT id, username, DATE_FORMAT(created_at, '%Y-%m-%d') as date_str FROM users");
$stmt->execute();

$output = fopen('php://output', 'w');
fputcsv($output, ['ID', '用户名', '日期']);

$i = 0;
while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
    fputcsv($output, $row);
    $i++;
    if ($i % 1000 === 0) {
        ob_flush();
        flush();
    }
}
fclose($output);

CSV 导出中文乱码(Excel 打开全是方块)

根本原因:Excel for Windows 默认用 ANSI(GBK/GB2312)打开 CSV,而 PHP 输出的是 UTF-8。不加 BOM,Excel 就认不出来。

  • 只对 UTF-8 编码的 CSV 加 BOM,且必须加在文件最开头(fopen('php://output') 后立即写)
  • BOM 是三个字节:\xEF\xBB\xBF,不能用 mb_convert_encoding 或其他方式生成
  • 加了 BOM 后,Content-Type 仍写 charset=utf-8,不要改成 gbk
  • 如果用 Notepad++ 查看,选“编码 → 转为 UTF-8-BOM”可验证是否生效
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="data.csv"');

$output = fopen('php://output', 'w');
fwrite($output, "\xEF\xBB\xBF"); // 写入 UTF-8 BOM
fputcsv($output, ['姓名', '地址', '备注']);
fputcsv($output, ['张三', '北京市朝阳区', '测试用户']);
fclose($output);

想先保存到服务器再提供下载链接

适合需要审计日志、定时批量导出、或文件要复用的场景。重点是路径权限、文件命名防覆盖、以及下载链接的安全控制。

  • 保存路径别放在 Web 可访问目录下(如 ./uploads/),建议放 /var/tmp/ 或项目外独立目录
  • 文件名必须唯一:用 uniqid() . '_' . date('Ymd_His'),避免并发写入冲突
  • 生成下载链接时,不要直接暴露物理路径,走一个中间 PHP 脚本(如 download.php?file=xxx.csv)做校验
  • 下载脚本里必须检查 $_GET['file'] 是否为合法格式(正则匹配 ^[a-z0-9_]+\.csv$),并用 basename() 防止路径遍历

保存示例(不输出,只写磁盘):

$filename = '/var/tmp/export_' . uniqid() . '_' . date('Ymd_His') . '.csv';
$output = fopen($filename, 'w');
fputcsv($output, ['ID', 'Name']);
fputcsv($output, [1, '测试']);
fclose($output);

// 记录到数据库或日志:成功写入 $filename
实际用的时候,BOM 和流式处理这两点最容易被跳过,一出问题就花半天排查。尤其是导出功能上线后数据量变大,原来小表没问题的代码突然挂掉——大概率是没关缓冲查询或没分批 flush。


# mysql  # php  # excel  # windows  # 编码  # 浏览器  # edge  # 字节  # 中文乱码  # csv  # ai  # win  # sql  # echo  # Array  # for  # date  # fopen  # Error  # pdo  # 字符串  # 循环  # var  # 并发  # bom  # 下载链接  # 流式  # 清空  # 的是  # 注册时间  # 朝阳区  # 放在  # 尤其是  # 遍历  # 很容易 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 网络优化76771 】 【 技术知识130152 】 【 IDC云计算60162 】 【 营销推广131313 】 【 AI优化88182 】 【 百度推广37138 】 【 网站推荐60173 】 【 精选阅读31334


相关推荐: php485读数据时阻塞怎么办_php485非阻塞读取设置技巧【详解】  Win11屏幕亮度突然变暗怎么解决_自动变暗问题处理  Windows 11登录时提示“用户配置文件服务登录失败”怎么办_Windows 11修复损坏的用户配置文件  如何在 PHP 中按相同键合并两个关联数组为二维数组  Win11怎么设置开机自动连接宽带_Windows11创建拨号连接计划任务  如何在 Go 中可靠地测试含 time.Time 字段的结构体  Win11怎么关闭系统声音_Win11系统提示音静音设置【详解】  php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】  Win10怎么更改用户名 Win10修改账户名称操作教程  Win11怎么设置开机问候语_自定义Win11锁屏提示信息【技巧】  MAC如何启用访达侧边栏显示_MAC Finder偏好设置与常用目录添加【教程】  Win11怎么修复系统文件_使用sfc命令修复Win11系统【技巧】  php485在macos下怎么配置_php485 macOS系统配置指南【解答】  如何用正则与预处理高效拦截带干扰符的恶意域名  如何在 Python 测试中动态配置 @backoff 装饰器的重试次数  Win10怎样卸载DockerDesktop_Win10卸载DockerDesktop步骤【步骤】  如何使用Golang编写单元测试_创建Test函数验证业务逻辑  Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】  php打包exe后无法写入文件_权限问题解决方法【教程】  mac怎么打开终端_MAC终端Terminal使用入门与常用命令【教程】  Windows怎样拦截QQ浏览器广告_Windows拦截QQ浏览器广告方法【方法】  Windows蓝屏错误0x0000001E怎么修复_KMODEEXCEPTIONNOTHANDLED排查  Win11怎么开启游戏工具栏_Windows11 Xbox Game Bar快捷键  Win11怎么设置虚拟内存最佳大小_Windows11性能选项自定义分页文件  c++中的Tag Dispatching是什么_c++利用标签分发优化函数重载【元编程】  Win11怎么设置默认PDF阅读器 Win11修改PDF打开方式【步骤】  Windows 10怎么隐藏特定更新补丁_Windows 10使用微软官方工具wushowhide.diagcab  php订单日志怎么导出excel_php导出订单日志到表格教程【教程】  php订单日志怎么按金额排序_php按订单金额排序日志方法【方法】  如何诊断并终止卡死的 multiprocessing 子进程  Win11资源管理器卡顿怎么办 Win11文件资源管理器重启技巧【优化】  Win11任务栏怎么固定应用 Win11将软件图标固定到底部【步骤】  Windows 11怎么设置默认解压软件_Windows 11为ZIP/RAR文件指定默认打开程序  Windows10蓝屏代码DPC_WATCHDOG_VIOLATION_Win10死机修复指南  Win11怎么开启游戏模式_Windows11优化游戏帧数设置指南  Win11怎么压缩文件 Win11自带压缩解压功能使用【教程】  Windows10电脑怎么连接蓝牙设备_Win10蓝牙配对失败解决方法  Windows电脑如何截屏?(四种快捷方法)  Win11此电脑不在桌面上_Windows 11桌面图标设置找回【步骤】  Win11怎么更改管理员名字 Win11修改账户名称详细步骤【教程】  php查询数据怎么导出csv_查询结果转csv文件保存【操作】  Windows10如何更改桌面背景_Win10个性化幻灯片放映设置  如何使用Golang匿名函数_快速定义临时函数逻辑  Python数据挖掘进阶教程_分类回归与聚类案例解析  ACF 教程:如何正确更新嵌套在多层 Group 字段内的子字段  Python邮件系统自动化教程_批量发送解析与模板应用  Win10怎样安装PPT模板_Win10安装PPT模板教程【步骤】  XML的“混合内容”是什么 怎么用DTD或XSD定义  c++中的可变参数模板(variadic templates)怎么用_c++模板编程黑魔法【C++11】  Win10系统怎么查看网络连接状态_Windows10网络和共享中心 

 2026-01-01

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

致胜网络推广营销网


致胜网络推广营销网

致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。

 915688610

 17370845950

 915688610@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.