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

PHP 導出 MySQL 數據到 CSV:指定編碼、標準 RFC 4180 兼容

     編輯:PHP 綜合知識

核心需求

  • 查詢結果流式寫入,避免大結果集佔用內存
  • 支援指定輸出編碼(UTF-8/GBK/CP1252 等)
  • 符合 RFC 4180:雙引號包裹含逗號/換行/引號的字段,雙引號轉義為雙雙引號
  • HTTP 下載響應頭正確

完整實現

<?php
// 1. 數據庫連接(建議 PDO)
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8", 'user', 'pass');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// 2. 查詢
$stmt = $pdo->query("SELECT id, name, email, created_at FROM users");

// 3. 響應頭
header('Content-Type: text/csv; charset=cp1252'); // 目標編碼
header('Content-Disposition: attachment; filename="export.csv"');

// 4. 輸出流
$out = fopen('php://output', 'w');

// 5. 寫入 BOM(Excel 識別 UTF-8 需 BOM,CP1252 不需)
// fputs($out, "\xEF\xBB\xBF"); // 僅 UTF-8 時啟用

// 6. 表頭
$firstRow = $stmt->fetch(PDO::FETCH_ASSOC);
if ($firstRow) {
    fputcsv($out, array_keys($firstRow), ',', '"');
    // 寫入第一行數據
    fputcsv($out, array_values($firstRow), ',', '"');
}

// 7. 循環寫入剩餘行
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    fputcsv($out, array_values($row), ',', '"');
}

fclose($out);
exit;
?>

手動實現 echocsv(不依賴 fputcsv,完全可控)

function echocsv($fields, $delimiter=',', $enclosure='"', $escape_char='\\') {
    $output = '';
    foreach ($fields as $field) {
        // 轉換編碼(如內部 UTF-8 → 輸出 CP1252)
        // $field = iconv('UTF-8', 'CP1252//IGNORE', $field);

        if (str_contains($field, $delimiter) ||
            str_contains($field, $enclosure) ||
            str_contains($field, "\n") ||
            str_contains($field, "\r")) {
            $field = $enclosure . str_replace($enclosure, $enclosure.$enclosure, $field) . $enclosure;
        }
        $output .= $field . $delimiter;
    }
    echo rtrim($output, $delimiter) . "\r\n";
}

編碼處理關鍵點

場景處理方式
數據庫 UTF-8 → 輸出 UTF-8無需轉換,建議加 BOM 兼容 Excel
數據庫 UTF-8 → 輸出 GBK/CP1252每字段 iconv('UTF-8', 'GBK//IGNORE', $val)
數據庫 GBK → 輸出 UTF-8每字段 iconv('GBK', 'UTF-8', $val)
不可轉換字符//IGNORE 忽略或 //TRANSLIT 音譯

大數據集優化

  • 游標/分批:LIMIT 1000 OFFSET ... 或 WHERE id > last_id ORDER BY id LIMIT 1000
  • 禁用緩衝:PDO MYSQL_ATTR_USE_BUFFERED_QUERY => false(需 mysqlnd)
  • 壓縮下載:Content-Encoding: gzip + gzencode 流式壓縮
  • 異步生成:後台任務生成文件,前端輪詢下載鏈接

常見坑

  1. fputcsv 默認區隔符 ,、包裹符 "、轉義符 \,Excel 完美兼容
  2. 字段包含 \r\n 會導致行數錯亂,必須包裹
  3. PHP < 5.5.4 fputcsv 不支援自定義轉義字符,需手動實現
  4. 導出前記得 set_time_limit(0)、ini_set('memory_limit', '512M')
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved