首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 導出 CSV 文件:瀏覽器下載與服務端保存完整實現

     編輯:PHP 相關知識

核心函數:export_csv() 通用實現

<?php
/**
 * 導出 CSV
 * @param array $data 二維數據陣列 [['col1','col2'], ...]
 * @param array $title 欄位標題 ['欄位1', '欄位2', ...]
 * @param string $filename 文件名(不含副檔名)
 * @param bool $download true=瀏覽器下載 false=服務端保存
 * @param string $saveDir 服務端保存目錄($download=false時必填)
 */
function exportCsv(array $data, array $title, string $filename = '', bool $download = true, string $saveDir = ''): void
{
    if (empty($data) || empty($title)) return;

    $filename = $filename ?: date('Y-m-d-H-i-s');
    $filename .= '.csv';

    // 構建 CSV 內容
    $csv = '';
    // 標題行
    $csv .= '"' . implode('","', $title) . "\"\r\n";

    // 數據行
    foreach ($data as $row) {
        // 雙引號轉義:"" 代表一個雙引號
        $row = array_map(fn($v) => str_replace('"', '""', $v), $row);
        $csv .= '"' . implode('","', $row) . "\"\r\n";
    }

    // 編碼轉換:UTF-8 → GBK/CP936 (Excel 兼容)
    $csv = mb_convert_encoding($csv, 'CP936', 'UTF-8');

    if ($download) {
        // 瀏覽器下載
        // IE 兼容:URL 編碼文件名
        $ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
        if (stripos($ua, 'MSIE') !== false || stripos($ua, 'Trident') !== false) {
            $filename = urlencode($filename);
            $filename = str_replace('+', '%20', $filename);
        }

        header('Content-Type: text/csv; charset=gbk');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Expires: 0');
        header('Pragma: public');
        echo $csv;
    } else {
        // 服務端保存
        if (!$saveDir || !is_dir($saveDir)) {
            throw new InvalidArgumentException('保存目錄無效');
        }
        $path = rtrim($saveDir, '/') . '/' . $filename;
        file_put_contents($path, $csv);
    }
}
?>

調用示例

1. 瀏覽器直接下載

<?php
$data = [
    ['111', '商品A', '12', '100%', '23', '50%', '4'],
    ['222', '商品B', '8', '80%', '15', '40%', '3'],
];
$header = ['參數ID', '參數名稱', '統計次數', '統計百分比', '唯一用戶', '用戶百分比', '人均次數'];

exportCsv($data, $header, '統計報表_20240115', true);
// 瀏覽器彈出下載:統計報表_20240115.csv
?>

2. 服務端保存(定時任務/後台生成)

<?php
$saveDir = '/var/www/data/exports';
exportCsv($data, $header, 'daily_report', false, $saveDir);
// 文件保存至:/var/www/data/exports/daily_report.csv
?>

大數據量優化:分塊輸出避免內存溢出

<?php
function exportCsvLarge(Generator $dataGen, array $title, string $filename): void
{
    $filename .= '.csv';
    header('Content-Type: text/csv; charset=gbk');
    header('Content-Disposition: attachment; filename="' . $filename . '"');

    // 直接輸出標題
    echo mb_convert_encoding('"' . implode('","', $title) . "\"\r\n", 'CP936', 'UTF-8');

    // 分塊輸出數據
    foreach ($dataGen as $row) {
        $row = array_map(fn($v) => str_replace('"', '""', $v), $row);
        echo mb_convert_encoding('"' . implode('","', $row) . "\"\r\n", 'CP936', 'UTF-8');
        // 可選:定期 flush
        // if ($i % 1000 === 0) flush();
    }
}

// 生成器示例:從數據庫游標逐行讀取
function getDataGenerator(PDO $pdo): Generator
{
    $stmt = $pdo->query('SELECT id, name, qty FROM products');
    while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
        yield $row;
    }
}
?>

常見坑與解決

問題原因解決
Excel 打開中文亂碼Excel 默認按系統編碼(GBK)打開 CSV輸出前 mb_convert_encoding($csv, 'CP936', 'UTF-8')
字段包含逗號/換行/雙引號破壞 CSV 格式字段用雙引號包裹,內部雙引號轉義為 ""
大文件導出內存溢出一次性構建巨大字符串使用 Generator 分塊輸出,或 fputcsv() 寫入臨時文件
IE 下載文件名亂碼IE 不支持 UTF-8 文件名urlencode() 文件名並替換 + 為 %20
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved