php允许内存大小在图像上传轮换时耗尽

use*_*914 5 php memory upload image

我有一个上传图像并根据方向旋转它们的脚本,我遇到的问题是,当上传带有EXIF标签的图像时,我收到一条错误消息:

允许的内存大小为33554432字节耗尽(尝试分配10368字节.

然后是它在错误日志中引用的行.

我注意到它只发生在带有EXIF标签的图像上.如果上传Photoshop或其他内容生成的普通图像,则可以正常工作.

实际的图像方向代码如下:

function correctImageOrientation($fullpath) {
  if (function_exists('exif_read_data')) {
    $exif = exif_read_data($fullpath);
    if($exif && isset($exif['Orientation'])) {
      $orientation = $exif['Orientation'];
      if($orientation != 1){
        $img = imagecreatefromjpeg($fullpath);
        $deg = 0;
        switch ($orientation) {
          case 3:
            $deg = 180;
            break;
          case 6:
            $deg = 270;
            break;
          case 8:
            $deg = 90;
            break;
        }
        if ($deg) {
          $img = imagerotate($img, $deg, 0);        
        }
        // then rewrite the rotated image back to the disk as $filename 
        imagejpeg($img, $fullpath, 100);
      } // if there is some rotation necessary
    } // if have the exif orientation info
  } // if function exists      
}
Run Code Online (Sandbox Code Playgroud)

error_log中发生内存问题的确切行实际上就是它所说的那一行:

$img = imagerotate($img, $deg, 0);
Run Code Online (Sandbox Code Playgroud)

我在脚本中调用它的方式如下:

$dirname = session::value('user_id');
$rotatedfile = '/home/myfolder/public_html/'.$dirname.'/'.$file_name;  
$rotatedfile = $this->correctImageOrientation($rotatedfile);
Run Code Online (Sandbox Code Playgroud)

我基本上想要实现的是旋转的图像保存在与原始文件相同的位置,基本上替换它.

同样,这只发生在包含EXIF信息的图像上.所有其他人上传没有问题.

什么可能导致这种内存分配问题?

Jak*_*uld 4

你的错误是这样的:

\n\n
\n

允许的内存大小 33554432 字节已耗尽(尝试分配\n 10368 字节)。

\n
\n\n

33554432 字节转换为 32 兆字节。所以这一切都意味着 PHP 在尝试执行某些工作时内存不足。

\n\n

您声称失败的图像具有 EXIF 信息,但这对我来说并不真实,因为这是造成此问题的原因。无论如何,解决问题的快速解决方案是通过添加ini_set连接到memory_limit函数的行来增加函数的 PHP 内存

\n\n

例如,检查后将其添加到此处if (function_exists('exif_read_data')) {。我将其设置为64M因为当运行此函数时,这将有效地使脚本内存容量加倍。代码在这里:

\n\n
function correctImageOrientation($fullpath) {\n  if (function_exists('exif_read_data')) {\n    ini_set('memory_limit', '64M');\n    $exif = exif_read_data($fullpath);\n    if($exif && isset($exif['Orientation'])) {\n      $orientation = $exif['Orientation'];\n      if($orientation != 1){\n        $img = imagecreatefromjpeg($fullpath);\n        $deg = 0;\n        switch ($orientation) {\n          case 3:\n            $deg = 180;\n            break;\n          case 6:\n            $deg = 270;\n            break;\n          case 8:\n            $deg = 90;\n            break;\n        }\n        if ($deg) {\n          $img = imagerotate($img, $deg, 0);        \n        }\n        // then rewrite the rotated image back to the disk as $filename \n        imagejpeg($img, $fullpath, 100);\n      } // if there is some rotation necessary\n    } // if have the exif orientation info\n  } // if function exists      \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

我基本上想要实现的是旋转图像被保存在与原始文件相同的位置,基本上替换它。

\n
\n\n

问题是您在 PHP 中使用 GD 库,当 PHP 将文件加载到系统中时,它会消耗内存,并且在尝试旋转图像时会消耗更多内存。

\n\n

具有 EXIF 信息的图像实际上可能具有比标准 72dpi 更高的 DPI。因此,虽然它们的尺寸表面上看起来与没有 EXIF 信息的另一张图像相同,但 300dpi 图像的尺寸实际上比 72dpi 图像大 4 倍左右。这很可能就是这些图像失败的原因;不是 EXIF 信息,而是整体 DPI。

\n\n

php.ini现在,您还可以通过更改读取为 的行来更改内存限制memory_limit = 32M。从技术上讲,这是可行的。但我不认为\xe2\x80\x99 对于一个失败的函数脚本来说是一种好的做法。

\n\n

\xe2\x80\x99s 因为当你更改设置时,php.ini它会增加所有 PHP 交互的 RAM;不仅仅是问题的问题。因此,您的服务器突然为 Apache(运行 PHP)消耗了更多 RAM 来执行基本功能以及消耗更多 RAM 的奇怪功能。这意味着如果这段代码每天只被访问几次,那么为什么要给每个 PHP 进程 32M RAM 的大型服务器带来负担呢?更好地用于ini_set('memory_limit', '64M');隔离像这样的 RAM 增加需求。

\n