必须显式指定xlsx reader类型,因.xls和.xlsx底层结构不同,自动探测易失败;需安装phpspreadsheet并开启zip/xml扩展,上传后校验后缀为xlsx,用iofactory::createreader('xlsx')加载,遍历行单元格跳过空行。

在ThinkPHP项目中导入.xlsx格式的Excel文件,必须显式指定Xlsx Reader类型,不能依赖自动探测——因为.xls和.xlsx底层结构完全不同,自动识别极易因扩展名被篡改或缺失而失败。
确认环境与依赖
确保已安装phpspreadsheet(推荐)或PHPExcel(兼容旧版TP3/TP5)。若用phpspreadsheet,执行composer require phpoffice/phpspreadsheet;若用PHPExcel,请将库文件放入Vendor/PHPExcel目录并正确引入。
【关键前提】PHP需开启zip和xml扩展,否则Xlsx读取会直接报错“Class 'ZipArchive' not found”或解析中断。
上传文件并校验后缀
前端表单必须设置enctype="multipart/form-data",name属性如file。
后端获取上传文件后,用pathinfo($file->getOriginalName(), PATHINFO_EXTENSION)安全提取扩展名,拒绝.csv——它不是Excel格式,phpspreadsheet会解析失败。
只允许xls和xlsx,其他一律拦截:if (!in_array(strtolower($ext), ['xls', 'xlsx'])) { $this->error('仅支持.xls或.xlsx文件'); }
选择Reader并加载文件
方法一:phpspreadsheet(推荐,TP6+及新版TP5适用)
根据后缀显式创建Reader:$reader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');(.xlsx用Xlsx,.xls用Xls)
【不可逆操作】不要用IOFactory::load(),它会尝试自动探测格式,一旦传入伪装成.xlsx的.xls文件,就会抛出异常且无法捕获具体原因。
方法二:PHPExcel(TP3/TP5旧项目)
$objReader = \PHPExcel_IOFactory::createReader('Excel2007');(对应.xlsx)或Excel5(对应.xls)
然后调用$objPHPExcel = $objReader->load($filePath);
读取工作表并跳过空行
第一步:获取当前活动工作表:$worksheet = $spreadsheet->getActiveSheet();
第二步:遍历所有行,但必须启用全单元格迭代,否则空列会被跳过:$rowIterator = $worksheet->getRowIterator();
第三步:对每一行,重置单元格迭代器以包含空单元格:$cellIterator->setIterateOnlyExistingCells(false);
第四步:逐单元格取值并收集,再用array_filter($rowData)判断是否全为空——这是唯一可靠跳过空行的方式。用getHighestRow()会漏掉末尾空行,用isEmpty()方法不可靠。
写入数据库前清洗数据
遍历$data数组时,跳过首行(表头):if ($i === 0) continue;
对每个字段做trim()和null转换:$value = is_null($cell->getValue()) ? '' : trim((string)$cell->getValue());
避免直接用toArray()——它会把整张表加载进内存,10万行Excel极易触发OOM;手动遍历行+单元格才能精确控制内存占用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











