如何读取受保护的Excel文件内容 - Laravel Excel 技术问题
问题原因
这个问题本质是Windows系统对互联网来源的文件自动添加了NTFS备用数据流(ADS)标记Zone.Identifier,并非Excel文件本身存在格式损坏或加密。Laravel Excel底层依赖的PhpSpreadsheet默认会跳过带这类特殊元数据标记的文件内容读取,就会返回空数组,手动打开Excel启用编辑并重存的操作,本质就是清除了这个ADS标记。
可行解决方案
方案1:服务端运行在Windows环境
直接在导入前删除文件的Zone.Identifier流即可,代码示例如下:
// 获取上传文件的本地临时路径 $filePath = $request->file('upload')->getRealPath(); // 调用powershell清除ADS标记,忽略不存在标记的报错 exec('powershell -Command "Remove-Item -Path \''.$filePath.'\' -Stream Zone.Identifier -ErrorAction SilentlyContinue"'); // 再执行原有导入逻辑 $importData = (new CustodianUsersImport)->toArray($filePath);
如果不想调用系统命令,也可以在导入类中添加只读配置,强制PhpSpreadsheet跳过元数据校验直接读单元格内容:
<?php namespace App\Imports; use Maatwebsite\Excel\Concerns\WithReadingOptions; class CustodianUsersImport implements WithReadingOptions { // 原有导入逻辑不变,新增这个方法 public function readingOptions(): array { return [ 'readDataOnly' => true, ]; } }
方案2:服务端运行在Linux/macOS环境
非Windows系统不会保留NTFS的ADS流,如果在这类环境下仍出现相同问题,说明文件本身设置了工作表保护,可通过以下代码解除后再导入:
$filePath = $request->file('upload')->getRealPath(); $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($filePath); // 解除当前工作表的保护限制 $spreadsheet->getActiveSheet()->getProtection()->setSheet(false); // 传入spreadsheet对象执行导入 $importData = (new CustodianUsersImport)->toArray($spreadsheet);
补充说明
如果上述方案都无法覆盖所有场景,可以在前端上传入口添加提示,告知用户若导入的是互联网下载的Excel,需先打开启用编辑后再上传,作为降级兼容方案。
内容的提问来源于stack exchange,提问作者Jesse Luke Orange
相关产品推荐
相关产品推荐

