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

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'=校验通过'];

}

相关文章:

  • Redis存储⑩Redis的事务_弱化的原子性
  • DeepSeek 提示词:定义、作用、分类与设计原则
  • 内容中台架构下智能推荐系统的算法优化与分发策略
  • Vue3 状态管理 - Pinia
  • 基于深度学习模型`U-Net`和`segment_anything`(SAM)库的实现示例
  • DuodooBMS源码解读之 cncw_ledger模块
  • Python连接MySQL数据库图文教程,Python连接数据库MySQL入门教程
  • 我的世界1.20.1forge开发教程(6)——自定义燃料,熔炼规则、配方
  • 【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter19-表单脚本
  • 《Python实战进阶》专栏 No.3:Django 项目结构解析与入门DEMO
  • ubuntu磁盘清理垃圾文件
  • LeetCode刷题---二分查找---441
  • 清华大学《DeepSeek与AI幻觉》(无套路免费分享)
  • lerobot调试记录
  • 传统的自动化行业的触摸屏和上位机,PLC是否会被取代?
  • Web 开发中的 5 大跨域标签解析:如何安全地进行跨域请求与加载外部资源
  • 路由基本配置
  • 神经网络八股(三)
  • 扩散模型中,Flow Matching的训练方式相比于 DDPM 训练方法有何优势?
  • 【GPU驱动】OpenGLES图形管线渲染机制
  • 新华社原香港分社副社长、深圳市委原副书记秦文俊逝世
  • 完善劳动关系协商协调机制,《共同保障劳动者合法权益工作指引》发布
  • 肖钢:一季度证券业金融科技投资强度在金融各子行业中居首
  • 广州医药集团有限公司原党委书记、董事长李楚源被“双开”
  • 新城市志|GDP万亿城市,一季度如何挑大梁
  • 公示资费套餐、规范营销行为,今年信息通信行业将办好这十件实事