当前位置: 首页> 最新文章列表> 用 header() 模拟下载 CSV 报表的场景

用 header() 模拟下载 CSV 报表的场景

M66 2025-05-18

在 Web 开发中,有时我们需要通过后端动态生成一个 CSV 报表,并提供给用户下载,而不是事先生成好一个文件放在服务器上供下载。PHP 的 header() 函数可以用来修改 HTTP 响应头,配合输出内容,就能实现这种“模拟下载”的效果。

本文将带你一步步实现这个功能。

步骤 1:准备 CSV 数据

首先,我们需要有一份要输出的 CSV 数据。可以是从数据库提取出来的,也可以是手工准备的数组。

$data = [
    ['姓名', '邮箱', '注册时间'],
    ['张三', 'zhangsan@m66.net', '2025-05-01 10:00:00'],
    ['李四', 'lisi@m66.net', '2025-05-02 11:30:00'],
    ['王五', 'wangwu@m66.net', '2025-05-03 14:15:00'],
];

步骤 2:设置 HTTP 头部

使用 header() 函数告诉浏览器这是一个文件下载响应,而不是普通的网页输出。特别重要的是:

  • Content-Type 告诉浏览器这是 CSV 文件;

  • Content-Disposition 设置附件形式,提供下载文件的名字;

  • Cache-ControlPragma 帮助避免缓存问题。

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="report.csv"');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

步骤 3:输出 CSV 内容

可以用 fopen('php://output', 'w') 将内容直接写入输出流,不需要生成中间文件。

$output = fopen('php://output', 'w');

foreach ($data as $row) {
    fputcsv($output, $row);
}

fclose($output);

完整示例代码

<?php
$data = [
    ['姓名', '邮箱', '注册时间'],
    ['张三', 'zhangsan@m66.net', '2025-05-01 10:00:00'],
    ['李四', 'lisi@m66.net', '2025-05-02 11:30:00'],
    ['王五', 'wangwu@m66.net', '2025-05-03 14:15:00'],
];

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="report.csv"');
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

$output = fopen('php://output', 'w');

foreach ($data as $row) {
    fputcsv($output, $row);
}

fclose($output);

注意事项

  1. 不要有多余输出
    在调用 header() 前,不能有任何多余的输出(包括空格、换行、BOM),否则会导致“Headers already sent”错误。

  2. 编码问题
    如果生成的 CSV 包含中文字符,最好用 UTF-8 BOM 或转换为 GBK,避免在 Excel 中打开出现乱码。

  3. 动态数据
    上例用的是静态数组,实际项目中往往需要从数据库中查询,再拼成数组。