当前位置: 首页 > article >正文

php处理图片出现内存溢出(Allowed memory size of 134217728 bytes exhausted)

错误

最近做图片上传功能时发现上传某些图片时报内存溢出错误。如下所示:

{
  "code": 0,
  "msg": "Allowed memory size of 134217728 bytes exhausted (tried to allocate 24576 bytes)",
  "data": {
    "code": 0,
    "line": 1806,
    "file": "\myweb\\ytems\app\\common.php",
    "message": "Allowed memory size of 134217728 bytes exhausted (tried to allocate 24576 bytes)",
    "trace": [
      {
        "function": "appShutdown",
        "class": "think\\initializer\\Error",
        "type": "->",
        "args": []
      }
    ]
  }
}

初步检查图片详情,发现图片并不大为861KB,服务器配置的内存上限是128MB,接口上传图片限制是2MB。排除图片大小限制问题。但发现此图片的分辨率为 5283x7727,初步怀疑是图片分辨率过大导致。

解决:

1、找出原因

通过对多张不同大小分辨率的图片进行测试发现果然是大分辨率的图片才会导致此报错,通过排查程序代码发现是在调用 imagecreatefromjpeg 图片处理函数时报的错误。

查看官方文档,才发现imagecreatefromjpeg在动态创建一个新图像时,是根据图片的分辨率(宽和高)在内存中生成一个新图像。

因此虽然用户上传的图片只有为861KB,但分辨率却高达 5283x7727,按照官方手册给出的公式可算出内存已达到(5283*7727*24/8*其它因素>117MB),加上其他程序消耗内存。很容易超过128MB内存上限,才导致内存溢出。

官方手册

imagecreatefromjpeg创建图像时占用内存公式:

总字节数=宽*高*每像素所占字节数*其它因素  (即 5283*7727*24/8*其它因素)

每像素所占字节数有2种计算方式:

每像素所占字节数
=位深/ 8
=色深(bits) *图像的通道(channels) / 8

(php使用getimagesize可以获取jpg图片的bits和channels,位深:如下图,在电脑上查看图片的属性->详细信息)

由此可知,imagecreatefromjpeg创建新图像的动作是在内存中实现,因此图像的宽和高很大程度上决定了内存的消耗。

2、在图片上传时限制图片的像素大小

相关函数如下:

/**
 * 校验图片像素大小

 * @param $sourceFile 原始图片文件
 * @param $$allowed_size 允许的像素大小
 * @return array
 * @throws Exception
 */
function valImage($sourceFile, $allowed_size=4000) {
    ini_set('memory_limit', '256M');

    // 检查GD库是否可用
    if (!extension_loaded('gd') || !function_exists('gd_info')) {
        //throw new Exception('GD库未安装');
        return ['code'=>4001,'msg'=>'GD库未安装'];
    }

    // 验证源文件
    if (!file_exists($sourceFile)) {
      //  throw new Exception('源文件不存在');
        return ['code'=>4002,'msg'=>'源文件不存在'];
    }

    // 获取图片信息
    $imageInfo = @getimagesize($sourceFile);
    if (!$imageInfo) {
        //throw new Exception('无效的图片文件');
        return ['code'=>4003,'msg'=>'无效的图片文件'];
    }

//    print_r($imageInfo);
     if($imageInfo[0] > $allowed_size|| $imageInfo[1]  > $allowed_size){
         return ['code'=>4000,'msg'=>'图片分辨率不可大于'.$allowed_size.'*'.$allowed_size.'像素'];
     }

     return ['code'=>200,'msg'=校验通过'];

}


http://www.kler.cn/a/557655.html

相关文章:

  • 【网络编程】服务器模型(二):并发服务器模型(多线程)和 I/O 复用服务器(select / epoll)
  • 【多语言生态篇四】【DeepSeek×Rust:安全内存管理实践】
  • verilog笔记
  • 【Leetcode 每日一题 - 扩展】1512. 好数对的数目
  • C语言实现的常见算法示例
  • 【算法】直接插入排序、折半插入排序、希尔排序
  • Dockerfile中volume功能作用
  • ok113i平台——更改根目录分区大小
  • 【深度学习】Pytorch的深入理解和研究
  • 跟着李沐老师学习深度学习(十二)
  • Cython学习笔记1:利用Cython加速Python运行速度
  • 算法日记25:01背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
  • HDFS入门与应用开发
  • 蓝桥杯——按键
  • 从零搭建微服务项目Pro(第1-1章——Quartz实现定时任务模块)
  • 实现 INFINI Console 与 GitHub 的单点登录集成:一站式身份验证解决方案
  • 国产编辑器EverEdit - 洞察秋毫!内置文件比较功能!
  • 正确清理C盘空间
  • 【AI】常见的AI工具地址和学习资料链接
  • INDEMIND:AI视觉赋能服务机器人,“零”碰撞避障技术实现全天候安全