php查询数据怎么导出csv_查询结果转csv文件保存【操作】
技术百科
蓮花仙者
发布时间:2026-01-01
浏览: 次 PHP导出CSV需用fputcsv流式处理并加UTF-8 BOM:清空缓冲、设置header、写BOM、逐行fetch,避免内存溢出与Excel乱码。
PHP 查询 MySQL 后直接输出 CSV 文件(浏览器下载)
最常用场景:后台导出报表,用户点击即下载。关键不是“保存到服务器”,而是让浏览器弹出下载对话框。
核心要点:fputcsv() 是 PHP 原生安全写 CSV 的函数,别用字符串拼接;输出前必须清空缓冲区、设置正确 header;MySQL 查询结果需转为二维数组(每行是 array)。
- 务必在
header()之前没有输出(包括空格、BOM、echo、var_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。
# ai
# 的是
# 放在
# 尤其是
# excel
# windows
# 朝阳区
# 很容易
# 浏览器
# 下载链接
# 清空
# win
# edge
# 循环
# Error
# 并发
# 编码
# 字节
# 中文乱码
# 字符串
# var
# bom
# php
# echo
# 遍历
# 流式
# for
# csv
# mysql
# sql
# 注册时间
# fopen
# pdo
# date
# Array
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- 如何在 ACF 中正确更新嵌套多层 Group 字
- 如何使用Golang实现错误包装与传递_Golan
- Windows11怎么用“记事本”自动换行与编码
- Mac的“调度中心”与“空间”怎么用_Mac多桌面
- Windows10电脑怎么设置防火墙出站规则_Wi
- php修改数据怎么批量改状态_批量更新status
- 如何在Golang中实现CI/CD流水线自动化测试
- Win11怎么关闭自动更新 Win11永久关闭系统
- Win11怎么格式化U盘_Win11系统U盘格式化
- Win11怎么关闭右下角弹窗_Win11拦截系统通
- Mac怎么设置登录项_Mac管理开机自启动程序【教
- 如何使用Golang模拟请求超时_Golang c
- Windows系统被恶意软件破坏后的恢复策略_错误
- 如何在Golang中使用replace替换模块_指
- Python网络异常模拟_测试说明【指导】
- Windows服务启动类型恢复方法_错误修改导致的
- Win11怎么设置默认PDF阅读器 Win11修改
- Win11此电脑不在桌面上_Windows 11桌
- Windows10如何查看保存的WiFi密码_Wi
- c++的static关键字有什么用 静态变量和静态
- php订单日志怎么导出excel_php导出订单日
- Django 测试数据库表缺失与字段未创建问题的完
- 如何在Golang中使用log包输出不同级别日志_
- Win11怎么设置ipv4地址_Windows 1
- Win11怎么开启游戏模式_Windows11优化
- php本地部署支持nodejs吗_php与node
- C#怎么使用委托和事件 C# delegate与e
- Mac如何调整Dock栏大小和位置_Mac程序坞个
- Win11声音忽大忽小怎么办 Win11音频增强功
- 如何在包含多值的列中精准搜索指定演员?
- Win10如何设置双wan路由器 Win10双wa
- MAC怎么设置程序窗口永远最前_MAC窗口置顶插件
- Golang如何遍历目录文件_Golang fil
- 如何使用Golang实现负载均衡_分发请求到多个服
- php485在php5.6下能用吗_php485旧
- mac怎么安装pip_MAC Python pip
- c++中如何计算坐标系中两点间距离_c++勾股定理
- Win11怎么关闭自动调节屏幕亮度_Windows
- 如何在Golang中使用内置函数_Golangle
- php485读数据时阻塞怎么办_php485非阻塞
- Python深度学习实战教程_神经网络模型构建与训
- Win11怎么关闭自动调节亮度 Win11禁用内容
- 如何使用Golang实现云原生应用弹性伸缩_自动应
- c++怎么调用nana库开发GUI_c++ 现代风
- Win10如何备份驱动程序_Win10驱动备份步骤
- Windows 10自带杀毒软件在哪_Window
- 如何使用Golang处理静态文件缓存_提高页面加载
- PHP的Workerman对架构扩展有啥帮助_应用
- Win11怎么禁用键盘自带键盘_Win11笔记本禁
- Go语言中slice追加操作的底层共享机制详解

是三个字节:
QQ客服