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

PHP 讀取 CSV 並輸出 HTML 表格:從基礎到生產級渲染

     編輯:PHP 相關知識

fgetcsv + 表格輸出:編碼轉換、XSS 防護、大文件分頁的完整方案

將 CSV 數據渲染為 HTML 表格是後台導入預覽、報表展示的常見需求。本文在基礎代碼基礎上,強化 UTF-8/BOM 處理、欄位轉義、內存控制、無障礙屬性,給出生產可用的渲染器。

基礎版代碼(教學用)

<?php
$fp = fopen('sample.csv', 'r') or die("can't open file");
print "<table>\n";
while ($csv_line = fgetcsv($fp)) {
    print '<tr>';
    for ($i = 0, $j = count($csv_line); $i < $j; $i++) {
        print '<td>' . htmlentities($csv_line[$i]) . '</td>';
    }
    print "</tr>\n";
}
print '</table>\n';
fclose($fp) or die("can't close file");

生產級 CSV 表格渲染器

<?php
class CsvTableRenderer
{
    private int $maxRows = 1000; // 防御性限制
    private int $rowCount = 0;
    private bool $hasHeader = true;

    public function __construct(
        private string $filepath,
        private string $inputEncoding = 'UTF-8', // CSV 實際編碼
        private string $outputEncoding = 'UTF-8'
    ) {}

    public function setMaxRows(int $n): self { $this->maxRows = $n; return $this; }
    public function setHasHeader(bool $b): self { $this->hasHeader = $b; return $this; }

    public function render(): string
    {
        $handle = fopen($this->filepath, 'r');
        if (!$handle) {
            throw new RuntimeException("無法打開文件: {$this->filepath}");
        }

        // 檢測並跳過 BOM
        $bom = fread($handle, 3);
        if ($bom !== "\xEF\xBB\xBF") {
            rewind($handle);
        }

        $html = ['<table class="csv-table">'];
        $isHeaderRow = $this->hasHeader;

        while (($row = fgetcsv($handle)) !== false) {
            if ($this->rowCount++ >= $this->maxRows) {
                $html[] = '<tr><td colspan="999" class="truncated">數據超過 ' . $this->maxRows . ' 行,已截斷顯示</td></tr>';
                break;
            }

            // 編碼轉換
            if ($this->inputEncoding !== $this->outputEncoding) {
                $row = array_map(fn($v) => mb_convert_encoding($v, $this->outputEncoding, $this->inputEncoding), $row);
            }

            $tag = $isHeaderRow ? 'th' : 'td';
            $html[] = '<tr>';
            foreach ($row as $cell) {
                // XSS 防護 + 保留換行
                $safe = htmlspecialchars($cell, ENT_QUOTES | ENT_SUBSTITUTE, $this->outputEncoding);
                $safe = nl2br($safe); // CSV 內換行轉 <br>
                $html[] = "<{$tag}>{$safe}</{$tag}>";
            }
            $html[] = '</tr>';
            $isHeaderRow = false;
        }

        fclose($handle);
        $html[] = '</table>';
        return implode("\n", $html);
    }
}

// 使用示例
echo (new CsvTableRenderer('data.csv'))
    ->setMaxRows(500)
    ->setHasHeader(true)
    ->render();

前端配套 CSS(語義化類名)

<style>
.csv-table { border-collapse: collapse; width: 100%; font-size: 0.9rem; }
.csv-table th { background: #f5f5f5; font-weight: 600; text-align: left; }
.csv-table th, .csv-table td { border: 1px solid #ddd; padding: 6px 10px; }
.csv-table tr:nth-child(even) td { background: #fafafa; }
.csv-table .truncated { color: #e74c3c; font-style: italic; text-align: center; }
</style>

大文件優化:流式輸出 + JavaScript 分頁

<?php
// 1. 後端只輸出 JSON(流式生成,不佔內存)
header('Content-Type: application/json; charset=utf-8');
$handle = fopen('big.csv', 'r');
echo '{"headers":[';
$first = true;
if (($row = fgetcsv($handle)) !== false) {
    foreach ($row as $cell) {
        echo ($first ? '' : ',') . json_encode($cell, JSON_UNESCAPED_UNICODE);
        $first = false;
    }
}
echo '],"rows":[';
$firstRow = true;
while (($row = fgetcsv($handle)) !== false) {
    echo ($firstRow ? '' : ',') . json_encode($row, JSON_UNESCAPED_UNICODE);
    $firstRow = false;
}
echo ']}';
fclose($handle);

前端用 DataTables、AG Grid 或輕量級 vanilla JS 實現虛擬滾動分頁,支撐百萬行數據流暢渲染。

避坑要點總結

問題原因解決
中文亂碼CSV 為 GBK/GB2312,頁面 UTF-8mb_convert_encoding 或 fopen 時指定編碼(PHP 8.1+ 支援)
HTML 注入/XSS直接輸出 cell 內容htmlspecialchars(ENT_QUOTES | ENT_SUBSTITUTE)
換行丟失CSV 單元格含 \nnl2br() 或 CSS white-space: pre-wrap
大文件 OOM一次性讀全文件流式 fgetcsv + 限制行數 / 前端虛擬滾動
BOM 干擾UTF-8 BOM 被作為第一個字段前綴fread 3 字節檢測並 rewind

規範的 CSV 表格渲染,不僅是「讀取→輸出」,更是編碼、安全、性能、體驗的綜合工程。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved