设置PHPExcel读取WPS文件时内存耗尽的问题
用过PHPExcel的都知道这玩意的坑不是一般的少啊,偏偏一般用户对excel有着莫名的偏爱。
这次遇到的问题就是使用这玩意读取WPS生成的excel,或者使用WPS打开过的excel时,老是会报内存耗尽之类的问题,具体问题当时忘记截图了。
好像是因为获取excel的数据内容的宽度和高度时,明明页面中没有值,但是WPS处理过的excel都会被PHPExcel以最大的高度和宽度读取数据,导致内存耗尽。所以读取文件时,需要加上过滤器。
过滤器类
namespace PHPExcelAssist;
class Filter implements \PHPExcel_Reader_IReadFilter{
protected $workSheetName;
protected $endColumn;
protected $endRow;
/**
* 构造函数,指定截止行,截止列
* Filter constructor.
* @param $workerSheetName string|array 表空间,支持多个表空间
* @param $endColumn string 截止列
* @param int $endRow 截止行
*/
public function __construct($workerSheetName,$endColumn,$endRow=0)
{
$this->workSheetName=$workerSheetName;
$this->endColumn=$endColumn;
$this->endRow=$endRow;
}
/**
* 实现过滤器
* @param \Column $column 当前列数
* @param \Row $row 当前行数
* @param string $worksheetName 表名
* @return bool
*/
public function readCell($column, $row, $worksheetName = '') {
// 只设置了一个表空间
if(!is_array($this->workSheetName) && $worksheetName!=$this->workSheetName){
return false;
}else{
// 设置了多个表空间
if(is_array($this->workSheetName) && !in_array($worksheetName,$this->workSheetName)){
return false;
}
}
// 设置了截止行,且当前行超过了指定行
if($this->endRow!=0 && $row>$this->endRow){
return false;
}
// 如果当前行的长度超过指定截止行,则也设置成错误
if(strlen($column)>strlen($this->endColumn)){
return false;
}
return true;
}
}
具体使用
public function organizeExcelData($excelFileInfo){
try{
// 加载上传文件
$fileType=\PHPExcel_IOFactory::identify($excelFileInfo['tmp_name']);// 获取读取文件的类型
$objReader=\PHPExcel_IOFactory::createReader($fileType);// 创建对应文件的读取器
$excelInstance=$objReader->setReadDataOnly(true)->setReadFilter(
// 调用过滤器
new Filter(
0,
"T",
0
)
)->load($excelFileInfo['tmp_name']);// 读取文件
$contentSheet=$excelInstance->getSheet(0);
// 这里的$contentSheet就是经过过滤的值,其中的宽度已经经过限制,基本上不会报内存耗尽之类的问题了
return $contentSheet;
}catch (Exception $e){
throw new Exception("在调用底层封装类处理Excel文件时出错:".$e->getMessage());
}
}
可以看到这里调用时传入了3个值,第一个值是sheet
的值,可以传入数组或者具体的值,这里因为只有一个sheet,所以传入0,第二个是宽度,这个在设计导入的Excel的时候肯定是定好的,所以可以传入对应的具体值,这里以T
为例而已,还可以是其他值,比如AZ
,ZZ
等。最后一个是高度,因为这个值是依据用户录入的,所以不确定,所以传入0