使用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导出数据时内存溢出处理相关推荐

  1. Java 中如何解决 POI 读写 excel 几万行数据时内存溢出的问题?(附源码)

    >>号外:关注"Java精选"公众号,菜单栏->聚合->干货分享,回复关键词领取视频资料.开源项目. 1. Excel2003与Excel2007 两个版本 ...

  2. POI3.8解决导出大数据量excel文件时内存溢出的问题

    POI3.8解决导出大数据量excel文件时内存溢出的问题 参考文章: (1)POI3.8解决导出大数据量excel文件时内存溢出的问题 (2)https://www.cnblogs.com/feng ...

  3. POI实现大数据EXCLE导入导出,解决内存溢出问题

    POI实现大数据EXCLE导入导出,解决内存溢出问题 参考文章: (1)POI实现大数据EXCLE导入导出,解决内存溢出问题 (2)https://www.cnblogs.com/huangjian2 ...

  4. php导出excel数据代码,phpspreadsheet导出数据到Excel的方法介绍(代码示例)

    本篇文章给大家带来的内容是关于phpspreadsheet导出数据到Excel的方法介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 之前我们使用PHP导出Excel数 ...

  5. springboot上传大文件时内存溢出的可能解决办法

    springboot上传大文件时内存溢出的可能解决办法 在springboot中上传大文件时要考虑内存的情况,一般我们会通过在执行服务时加入-Xms512m -Xmx512m等参数加大堆内存,但这是指 ...

  6. mysql 1455_关于Oracle 11g导出数据时 报 ORA-1455错误的处理

    关于Oracle 11g导出数据时 报 ORA-1455错误的处理,由于导出的该用户的表可能存在空数据表,那么可能就会出现此其异常. 关于Oracle 11g导出数据时 报 ORA-1455错误的处理 ...

  7. SqlServer的SSIS导入导出数据时找不到连接错误处理

    SqlServer的SSIS导入导出数据时找不到连接错误处理 报错: 找不到连接"SourceConnectionOLEDB".如果找不到特定的连接元素,Connections集合 ...

  8. vue2打包时内存溢出解决方案

    vue2打包时内存溢出解决方案 参考文章: (1)vue2打包时内存溢出解决方案 (2)https://www.cnblogs.com/ZT0219/p/7872258.html 备忘一下.

  9. 解决 pandas 读取数据时内存过大的问题

    解决 pandas 读取数据时内存过大的问题 背景: 在我们使用pandas进行数据处理的时候,有时候发现文件在本地明明不大,但是用pandas以DataFrame形式加载内存中的时候会占用非常高的内 ...

最新文章

  1. Docker 入门系列(2)- Docker 镜像, 免 sudo 使用 docker 命令、获取查看、修改镜像标签、查找删除创建镜像、导入导出镜像
  2. JS中的!=、== 、!==、===的用法和区别。
  3. tensorflow 无法执行sess =tf .session ()_深度学习|费解的tensorflow
  4. R之ddlpy函数学习[转载]
  5. tomcat server.xml配置详解
  6. 【React Native 安卓开发】----(Flexbox布局)【第二篇】
  7. 【转】兄弟俩玩的2000亿美元的公司,盖茨与鲍尔默:微软双雄上演终极接力
  8. C#开源爬虫NCrawler源代码解读以及将其移植到python3.2(4)
  9. 清除数据库日志操作_SQL SERVER
  10. ES6语法及vue复习
  11. 跑深度模型的显卡_人工智能研究者应该选择哪款显卡?
  12. java ltp4j_ltp工具使用配置
  13. mov 指令用c语言写,汇编总结:mov指令
  14. C++技术——构造法
  15. 虚拟化 : VT-x VT-d VT-c的分别
  16. Jetson TX2刷机(Jetpack4.2.0)
  17. Quora如何在快速开发中保持高品质代码
  18. pyautogui使用经验
  19. 基于STM32与红外感应开关的自动门设计与实现(结构+设计)
  20. 图像处理中 光场(Light Field)简介及理解

热门文章

  1. 背包九讲--背包综合题目
  2. Ubuntu 更改语言为中文
  3. ICLR 21可信多视图分类论文笔记:Trusted Multi-view Classification
  4. Circle of Mistery 2023牛客暑期多校训练营5 B
  5. WarGame系列之Natas(Web安全)通关指北(初级篇0-10)详细版
  6. 有趣好玩的APP,宅家再也不用担心会无聊了
  7. 使用Calendar类得到一年中的二月有多少天
  8. QQ的个人中心模块思维导图
  9. 多伦多大学密西莎加计算机科学,多伦多大学密西沙加分校
  10. 我和nupt集训队的故事