【问题标题】:Freeing up memory during an image resize script (GD)在图像调整大小脚本 (GD) 期间释放内存
【发布时间】:2015-07-02 15:29:27
【问题描述】:

我有以下代码从HTML <form> 获取$_POSTed 图像并上传它们。然后它会重新调整它们的大小(最多两倍)并将这些较小的图像保存到同一个目录中。

但是,我在处理较大的文件时内存不足。

我的问题不是“如何防止发生 X 错误?”,而是“如何释放此脚本正在使用的内存以便它可以继续运行?”

<?php
if (!isset($_POST['SiteID']) || !filter_var($_POST['SiteID'], FILTER_VALIDATE_INT)) {
    header("Location: ./");
    exit();
}
$SiteID = $_POST['SiteID'];

if (!isset($_POST['GalleryID']) || !filter_var($_POST['GalleryID'], FILTER_VALIDATE_INT)) {
    header("Location: ./?SiteID=" . $SiteID . "&error=upload");
    exit();
}
$GalleryID = $_POST['GalleryID'];

$ImageFile = $_FILES['ImageFile'];

$Extensions = array("jpg", "jpeg");
$Timestamp = date("U");

require_once("db.php");

for ($X = 0; $X < count($_FILES['ImageFile']['name']); $X++) {
    $Extension = strtolower(pathinfo($ImageFile['name'][$X], PATHINFO_EXTENSION));
    if (in_array($Extension, $Extensions)) {
        if ($ImageFile['error'][$X] === UPLOAD_ERR_OK) {
            if ($ImageFile['size'][$X] <= 5 * 1024 * 1024) {
                $Filename = $GalleryID . "-" . $Timestamp . "-" . $X . "." . $Extension;
                move_uploaded_file($ImageFile['tmp_name'][$X], "uploads/" . $Filename);
                mysql_query("INSERT INTO NewGalleryImages SET GalleryID = $GalleryID, ImageFile = '$Filename', ImageCaption = ''");
                $Dimensions = getimagesize("uploads/" . $Filename);
                $Width = ($Dimensions[0] > 768 ? 768 : $Dimensions[0]);
                $Height = ($Dimensions[1] / $Dimensions[0]) * $Width;
                $Expl = explode(".", $Filename);
                $LargeFilename = $Expl[0] . "_gallery." . $Expl[1];
                $Source = "uploads/" . $Filename;
                $Canvas = imagecreatetruecolor($Width, $Height);
                $LargeImage = imagecreatefromjpeg($Source);
                imagecopyresampled($Canvas, $LargeImage, 0, 0, 0, 0, $Width, $Height, $Dimensions[0], $Dimensions[1]);
                imagejpeg($Canvas, "uploads/" . $LargeFilename, 100);
                imagedestroy($Canvas);
                $Width = 200;
                $Height = ($Dimensions[1] / $Dimensions[0]) * $Width;
                $Expl = explode(".", $Filename);
                $ThumbFilename = $Expl[0] . "_thumb." . $Expl[1];
                $Source = "uploads/" . $Filename;
                $Canvas = imagecreatetruecolor($Width, $Height);
                $ThumbImage = imagecreatefromjpeg($Source);
                imagecopyresampled($Canvas, $ThumbImage, 0, 0, 0, 0, $Width, $Height, $Dimensions[0], $Dimensions[1]);
                imagejpeg($Canvas, "uploads/" . $ThumbFilename, 100);
                imagedestroy($Canvas);
            } else {
                mysql_close();
                header("Location: ./?SiteID=" . $SiteID . "&error=size");
                exit();
            }
        } else {
            mysql_close();
            header("Location: ./?SiteID=" . $SiteID . "&error=unknown");
            exit();
        }
    } else {
        mysql_close();
        header("Location: ./?SiteID=" . $SiteID . "&error=type");
        exit();
    }
}

mysql_close();
header("Location: ./?SiteID=" . $SiteID . "&uploaded");
exit();

// var_dump($_POST);
// var_dump($_FILES);
// var_dump($ImageFile);
?>

我在 PHP 文档中阅读了有关 imagedestroy() 的信息,并尝试在几个地方将其添加到我的脚本中,但是 1)我不确定我正在破坏正确的资源,并且 2)我我不确定它实际上是在清除内存。

我目前在服务器上有以下设置:

post_max_size = 64M
upload_max_filesize = 10M
max_input_time = 60
max_input_nesting_level = 64
max_execution_time = 120
memory_limit = 512M
max_input_vars = 1000

这是我收到的错误消息:

Fatal error: Allowed memory size of 536870912 bytes exhausted
(tried to allocate 29440 bytes) in
/var/www/vhosts/example.com/httpsdocs/gallery-upload.php
on line 36

我觉得奇怪的是,无论我创建多少 memory_limit,它需要分配的“额外”总是相同的:29440 bytes

如果我单独上传图片,脚本运行正常,但一次上传两个以上会引发错误。超过 512MB 的内存来调整两个图像的大小似乎过多,不是吗?还是内存不够?我不确定这台服务器能节省多少……! 如何减少总内存使用量?

【问题讨论】:

    标签: php file-upload gd image-uploading


    【解决方案1】:

    在玩了一会儿之后,我设法让我的脚本工作了。我需要做的是在新图像上使用imagedestroy()每次调整大小后的原始图像,即:

    imagedestroy($LargeImage);
    imagedestroy($Canvas);
    

    我不确定这是否是可以释放内存的所有方法,但它正在工作(目前)。我相信很快有人会用更大的图像文件再次测试我的内存限制......

    【讨论】:

    • 还有imagedestroy($ThumbImage)
    猜你喜欢
    • 2016-03-18
    • 2017-12-09
    • 1970-01-01
    • 2012-08-12
    • 2010-11-03
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    • 2011-05-17
    相关资源
    最近更新 更多