防止GD图像库内存不足的故障安全方法? (PHP)
Posted
技术标签:
【中文标题】防止GD图像库内存不足的故障安全方法? (PHP)【英文标题】:A fail-safe way to prevent GD image library from running out of memory? (PHP) 【发布时间】:2009-07-13 00:49:24 【问题描述】:有没有办法防止 php GD image library 内存不足?如果上传的图片太大,GD 往往会耗尽内存,终止脚本。我希望它抛出一个可捕获的异常或类似的东西,但可惜它没有。
现在我正在使用一个拼凑的脚本,它首先发出一个ini_set('memory_limit', '128M')
,如果这样我通常都准备好了。取决于服务器配置,尽管这可能是不可能的,所以我依靠一种算法来尝试估计所需的内存量(考虑分辨率、颜色深度、通道和软糖因素),然后将其与memory_get_usage()
如果函数存在,则进行粗略估计。
到目前为止,整个事情都有效,但它远非优雅,并且在某些极端情况下会失败,我敢肯定。有没有更好的方法来做到这一点,即如果必须让 GD 优雅地失败,而不是让一切都停下来?
【问题讨论】:
大型 JPEG 图像(非 PNG 或其他类型)可以在加载时调整大小,有关详细信息,请参阅此答案:***.com/questions/12661/… 这取决于你有多少内存。如果您有 512mb 的内存,并且您正在尝试调整大约 10k 像素的 png 图像的大小。您将几乎立即达到 1.5GB 的 ram 使用量。我的建议是 A) 获得更多内存 B) 使用函数来构建图像并破坏它们,并使用内存使用函数来查看每个处理后的图像。使用刷新函数转储和清除缓冲区... 【参考方案1】:购买更多内存! :-P
说真的,无法处理内存不足的问题,因为您执行的任何操作都需要更多内存。
最好的办法是根据当前内存设置限制上传的图片大小。
【讨论】:
大声笑,给我买一台内存更大的主机。 ;-) 好吧,我至少希望 GD 估计它自己的内存使用情况,而不是我不得不做容易出错的猜测然后屏住呼吸。我不能只通过文件大小来限制图像。具有高度压缩、高分辨率 JPG 的小文件可能比具有低分辨率 PNG 的大文件占用更多内存。这就是为什么我不得不依靠上面提到的计算。【参考方案2】:创建图像后。
imagepng($image);
imagedestroy($image);
将消除内存问题
【讨论】:
这应该被标记为答案,它对我来说就像一个魅力。 这应该不被标记为答案。销毁图像可以节省内存使用,但绝不会使 GD 表现得更优雅。 投反对票。这不是解决方案,而是避免内存泄漏的标准过程。如果仅一个图像已经大到足以达到内存限制,它不会阻止 GD 导致内存溢出。【参考方案3】:还有另一种方法,但它可能会很耗时,因为图像编辑过程的某些部分会重复多次,但您可以将内存限制设置为您的估计值,然后尝试处理图像,如果它失败捕获异常,增加内存限制,然后再次处理图像 - 重复此操作直到你成功或达到某个内存限制 - 此时你会向用户抛出一条错误消息,解释他们的图像太大而无法使用。
编辑:要捕获内存不足错误,您可以使用以下解决方案:http://au2.php.net/set_error_handler#35622
【讨论】:
再读一遍,AFAIK 没有什么可捕获的东西被抛出。这是一个一次性的工作或它不操作。除非你能告诉我如何捕捉内存不足的错误,这就是我所要求的。 :) 我必须看看这是否真的有帮助,正如 Nick 所说,我必须在错误发生后使用更多内存来处理错误。【参考方案4】:要捕获 PHP 的致命错误,例如“内存不足”或“PHP 致命错误:允许的内存大小为 8388608 字节已用尽(试图分配…字节)”,请参见此处:http://php.net/manual/en/function.set-error-handler.php#88401
【讨论】:
一旦 PHP 脚本内存不足,它就无法调用关闭函数,因为这需要分配更多内存。【参考方案5】:做一些测试来检查每个gd
函数需要多少内存。
imagecreatetruecolor
似乎需要width*height*5 bytes
。
imagepng
似乎需要width*height*4 bytes
。
【讨论】:
为什么imagecreatetruecolor
每个像素需要 5 个字节?听起来是个奇数。
因为 alpha 支持是在 imagecreate 之后很久才添加的,而且很多函数可能假设第 4 字节总是 0,所以它不能被使用......或者他们认为/看到它太复杂了,无法使用它并创建了一个新的。
您是否也有在其上加载现有图像的经验?例如对于jpg还是png?我使用 x * y * ~5 表示 jpg, ~8 表示 png,在当前内存使用情况之上。如果超过内存限制,我设置一个例外。但是:将 64M 设置为限制并上传 2MB 的 jpg 有时会破坏操作。 Jpg 似乎有时会使用更多的内存。压缩?还有其他exif数据吗?哪里可以改进计算?
所有对 imagepng、imagejpeg、imagegif、imagebmp、imagewbmp、imagexbm、imagewebp、imagegd、imagegd2 的调用将使用宽度 * 高度 * 一些 coef 字节,除了现有的资源(来自所有 imagecreate , imagecreatetruecolor 和 imagecreatefrom*) (可能还有一些用于压缩、格式和所有的临时内存)。 imageloadfont 和 imagepsloadfont 也会使用一些内存。必须使用 imdestroy 销毁旧资源以避免泄漏。【参考方案6】:
您最好的选择是停止尝试计算它需要多少内存,一开始就将其最大化 - 如果您有 4 GB 可用,请告诉图像脚本使用 2 到 4 GB 左右,当脚本结束时,让它恢复正常,这将涵盖所有潜在的致命情况。无论如何,这是我能想到的唯一“故障安全”方式......
【讨论】:
这就是我正在尝试做的事情,但这在共享主机上几乎不可能。对于这些情况,我正在做最佳猜测计算以防止挂断。 将 PHP 内存限制设置为等于系统拥有的 RAM 总量,或任何远程接近它的地方,将允许用户通过您的图像脚本对您执行 DOS。事先确定需要多少 RAM 是我能想到的唯一方法,这可以防止这种类型的 DOS。以上是关于防止GD图像库内存不足的故障安全方法? (PHP)的主要内容,如果未能解决你的问题,请参考以下文章