无需第三方库实现PHP从SQL导出无报错的XLS/XLSX文件
解决无第三方库导出XLSX/XLS无报错的问题
问题根源
你当前的代码本质是输出制表符分隔的纯文本,只是修改了文件名和HTTP Content-Type,但实际内容和XLSX/XLS的格式完全不匹配——XLSX是基于OpenXML的压缩包格式,XLS是二进制BIFF格式,因此Excel会检测到格式与扩展名不符并报错。
优先实现:无第三方库导出XLSX
XLSX本质是包含特定XML文件的ZIP压缩包,我们可以用PHP内置的ZipArchive类(属于PHP原生扩展,无需额外安装第三方库)来构建标准格式:
代码示例
// DB Connection included by a config.php file $sql = $db->prepare("SELECT * FROM myTable"); $sql->execute(); $result = $sql->fetchAll(PDO::FETCH_ASSOC); // 生成符合标准的XLSX文件 function createXLSX($records) { if (empty($records)) return false; // 创建临时文件存储ZIP内容 $tempFile = tempnam(sys_get_temp_dir(), 'xlsx'); $zip = new ZipArchive(); $zip->open($tempFile, ZipArchive::CREATE | ZipArchive::OVERWRITE); // 1. 添加XLSX必需的核心配置文件 // [Content_Types].xml $contentTypes = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"> <Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> <Default Extension="xml" ContentType="application/xml"/> <Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/> <Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/> <Override PartName="/xl/_rels/workbook.xml.rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/> </Types>'; $zip->addFromString('[Content_Types].xml', $contentTypes); // _rels/.rels $rels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml"/> </Relationships>'; $zip->addFromString('_rels/.rels', $rels); // xl/_rels/workbook.xml.rels $workbookRels = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml"/> </Relationships>'; $zip->addFromString('xl/_rels/workbook.xml.rels', $workbookRels); // xl/workbook.xml $workbook = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"> <sheets> <sheet name="导出数据" sheetId="1" r:id="rId1"/> </sheets> </workbook>'; $zip->addFromString('xl/workbook.xml', $workbook); // 2. 构建工作表数据(sheet1.xml) $sheetXml = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <sheetData>'; // 添加表头 $headers = array_keys($records[0]); $sheetXml .= '<row>'; foreach ($headers as $header) { $sheetXml .= '<c t="inlineStr"><is><t>' . htmlspecialchars($header) . '</t></is></c>'; } $sheetXml .= '</row>'; // 添加数据行 foreach ($records as $row) { $sheetXml .= '<row>'; foreach ($row as $cell) { $cellValue = htmlspecialchars((string)$cell); $sheetXml .= '<c t="inlineStr"><is><t>' . $cellValue . '</t></is></c>'; } $sheetXml .= '</row>'; } $sheetXml .= '</sheetData></worksheet>'; $zip->addFromString('xl/worksheets/sheet1.xml', $sheetXml); // 关闭ZIP包 $zip->close(); return $tempFile; } // 输出XLSX文件 $xlsxFile = createXLSX($result); if ($xlsxFile) { header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment; filename=Export.xlsx'); header('Content-Length: ' . filesize($xlsxFile)); readfile($xlsxFile); unlink($xlsxFile); // 清理临时文件 } exit;
说明
- 严格遵循OpenXML标准构建XLSX结构,Excel打开不会有格式报错
- 所有内容做
htmlspecialchars转义,避免XML解析错误 - 使用临时文件存储ZIP内容,输出后自动删除,无残留文件
导出XLS格式(无第三方库)
XLS是二进制BIFF格式,手动编写完整格式复杂度极高,推荐用HTML表格模拟的方式,Excel可直接识别且无报错:
代码示例
// DB Connection included by a config.php file $sql = $db->prepare("SELECT * FROM myTable"); $sql->execute(); $result = $sql->fetchAll(PDO::FETCH_ASSOC); header('Content-Type: application/vnd.ms-excel'); header('Content-Disposition: attachment; filename=Export.xls'); // 输出标准HTML表格 echo '<table>'; // 输出表头 echo '<tr>'; foreach (array_keys($result[0]) as $header) { echo '<th>' . htmlspecialchars($header) . '</th>'; } echo '</tr>'; // 输出数据行 foreach ($result as $row) { echo '<tr>'; foreach ($row as $cell) { echo '<td>' . htmlspecialchars((string)$cell) . '</td>'; } echo '</tr>'; } echo '</table>'; exit;
说明
- 输出标准HTML表格,设置
application/vnd.ms-excel的Content-Type,Excel会将其识别为XLS格式 - 对内容做转义处理,避免特殊字符导致格式混乱
- 实现简单,无需处理复杂的二进制结构
内容的提问来源于stack exchange,提问作者Trombone0904
相关产品推荐
相关产品推荐

