使用phpspreadsheet导出数据时内存溢出处理
使用phpspreadsheet进行导出excel的时候遇到了内存溢出的问题,官方提供了memory saving的解决方案,官方文档中提供了APCu、redis和memcache的缓存方案,但是在这些缓存方案都需要安装相应的扩展并且都为内存型缓存,数据量一大的话就会大大占用系统的内存,可能会影响项目的正常运行的,于是就自行实现了一种文件缓存的方式,实测可以减少导excel表时一半的内存使用量,在此把代码贴在下面记录一下。
//调用示例 在实例化spreadersheet对象前设置
\PhpOffice\PhpSpreadsheet\Settings::setCache(new \Excel\FileCache('/tmp/excel_cache'));
<?php
namespace Excel;
use Psr\SimpleCache\CacheInterface;
class FileCache implements CacheInterface {const FILE_SIZE = 3000; //读取时单次缓存行数(文件分割行数)private $cache_key = [];private $cache = [], $file_handles = [], $cache_dir, $file_prefix;private function delCacheDir($path) {if (is_dir($path)) {foreach (scandir($path) as $val) {if ($val != "." && $val != "..") {if (is_dir($path . $val)) {$this->delCacheDir($path . $val . '/');@rmdir($path . $val . '/');} else {unlink($path . $val);}}}}}private function getFilenameByKey($key) {$arr = explode('.', $key);$end = array_pop($arr);$dir = $this->cache_dir . implode('_', $arr);if (! is_dir($dir)) {mkdir($dir, 0777, true);}$line = '';$len = strlen($end);for ($i = 0; $i < $len; $i++) {if (is_numeric($end[$i])) {$line .= $end[$i];}}$suf = (int)round($line / self::FILE_SIZE);return $dir . '/' . $this->file_prefix . $suf;}private function getFileHandleByKey($key) {$filename = $this->getFilenameByKey($key);if (! array_key_exists($filename, $this->file_handles)) {$fp = fopen($filename, 'w+');if (! $fp) {throw new \Exception('生成缓存文件失败');}$this->file_handles[$filename] = $fp;}return $this->file_handles[$filename];}public function __construct($cache_dir) {$this->cache_dir = rtrim($cache_dir, '/') . '/';$this->file_prefix = uniqid();}public function __destruct() {$this->clear();}public function clear() {$this->cache_key = [];foreach ($this->file_handles as $file_handle) {isset($file_handle) && fclose($file_handle);}$this->delCacheDir($this->cache_dir);return true;}public function delete($key) {$key = $this->convertKey($key);unset($this->cache_key[$key]);return true;}public function deleteMultiple($keys) {foreach ($keys as $key) {$this->delete($key);}return true;}public function get($key, $default = null) {$key = $this->convertKey($key);if ($this->has($key)) {$seek = $this->cache_key[$key];if (array_key_exists($key, $this->cache) && $this->cache[$key]['seek'] == $seek) {return $this->cache[$key]['data'];}$fp = $this->getFileHandleByKey($key);$this->cache = [];fseek($fp, 0);while (! feof($fp)) {$data = fgets($fp);$data = json_decode(trim($data), 1);if ($data['key'] == $key && $data['seek'] == $seek) {$default = unserialize($data['data']);}$this->cache[$data['key']] = ['data' => unserialize($data['data']),'seek' => $data['seek']];}}return $default;}public function getMultiple($keys, $default = null) {$results = [];foreach ($keys as $key) {$results[$key] = $this->get($key, $default);}return $results;}public function has($key) {$key = $this->convertKey($key);return array_key_exists($key, $this->cache_key);}public function set($key, $value, $ttl = null) {$key = $this->convertKey($key);if ($this->has($key) && $this->get($key) == $value) {return true;}$fp = $this->getFileHandleByKey($key);fseek($fp, 0, SEEK_END);$seek = ftell($fp);$this->cache_key[$key] = $seek;fwrite($fp, json_encode(['key' => $key,'data' => serialize($value),'seek' => $seek]) . PHP_EOL);unset($value);return true;}public function setMultiple($values, $ttl = null) {foreach ($values as $key => $value) {$this->set($key, $value);}return true;}private function convertKey($key) {return preg_replace('/^phpspreadsheet\./', '', $key); //remove prefix "phpspreadsheet."}
}
ps. 后来找了一下,发现网上也存在挺多好用的文件缓存的第三方库,大家也可以自行在网上搜索一下
使用phpspreadsheet导出数据时内存溢出处理相关推荐
- Java 中如何解决 POI 读写 excel 几万行数据时内存溢出的问题?(附源码)
>>号外:关注"Java精选"公众号,菜单栏->聚合->干货分享,回复关键词领取视频资料.开源项目. 1. Excel2003与Excel2007 两个版本 ...
- POI3.8解决导出大数据量excel文件时内存溢出的问题
POI3.8解决导出大数据量excel文件时内存溢出的问题 参考文章: (1)POI3.8解决导出大数据量excel文件时内存溢出的问题 (2)https://www.cnblogs.com/feng ...
- POI实现大数据EXCLE导入导出,解决内存溢出问题
POI实现大数据EXCLE导入导出,解决内存溢出问题 参考文章: (1)POI实现大数据EXCLE导入导出,解决内存溢出问题 (2)https://www.cnblogs.com/huangjian2 ...
- php导出excel数据代码,phpspreadsheet导出数据到Excel的方法介绍(代码示例)
本篇文章给大家带来的内容是关于phpspreadsheet导出数据到Excel的方法介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 之前我们使用PHP导出Excel数 ...
- springboot上传大文件时内存溢出的可能解决办法
springboot上传大文件时内存溢出的可能解决办法 在springboot中上传大文件时要考虑内存的情况,一般我们会通过在执行服务时加入-Xms512m -Xmx512m等参数加大堆内存,但这是指 ...
- mysql 1455_关于Oracle 11g导出数据时 报 ORA-1455错误的处理
关于Oracle 11g导出数据时 报 ORA-1455错误的处理,由于导出的该用户的表可能存在空数据表,那么可能就会出现此其异常. 关于Oracle 11g导出数据时 报 ORA-1455错误的处理 ...
- SqlServer的SSIS导入导出数据时找不到连接错误处理
SqlServer的SSIS导入导出数据时找不到连接错误处理 报错: 找不到连接"SourceConnectionOLEDB".如果找不到特定的连接元素,Connections集合 ...
- vue2打包时内存溢出解决方案
vue2打包时内存溢出解决方案 参考文章: (1)vue2打包时内存溢出解决方案 (2)https://www.cnblogs.com/ZT0219/p/7872258.html 备忘一下.
- 解决 pandas 读取数据时内存过大的问题
解决 pandas 读取数据时内存过大的问题 背景: 在我们使用pandas进行数据处理的时候,有时候发现文件在本地明明不大,但是用pandas以DataFrame形式加载内存中的时候会占用非常高的内 ...
最新文章
- Docker 入门系列(2)- Docker 镜像, 免 sudo 使用 docker 命令、获取查看、修改镜像标签、查找删除创建镜像、导入导出镜像
- JS中的!=、== 、!==、===的用法和区别。
- tensorflow 无法执行sess =tf .session ()_深度学习|费解的tensorflow
- R之ddlpy函数学习[转载]
- tomcat server.xml配置详解
- 【React Native 安卓开发】----(Flexbox布局)【第二篇】
- 【转】兄弟俩玩的2000亿美元的公司,盖茨与鲍尔默:微软双雄上演终极接力
- C#开源爬虫NCrawler源代码解读以及将其移植到python3.2(4)
- 清除数据库日志操作_SQL SERVER
- ES6语法及vue复习
- 跑深度模型的显卡_人工智能研究者应该选择哪款显卡?
- java ltp4j_ltp工具使用配置
- mov 指令用c语言写,汇编总结:mov指令
- C++技术——构造法
- 虚拟化 : VT-x VT-d VT-c的分别
- Jetson TX2刷机(Jetpack4.2.0)
- Quora如何在快速开发中保持高品质代码
- pyautogui使用经验
- 基于STM32与红外感应开关的自动门设计与实现(结构+设计)
- 图像处理中 光场(Light Field)简介及理解