使用PHP getimagesize和imagecreate与Google App Engine和Google Cloud Storage

时间:2016-08-07 05:15:35

标签: php google-app-engine php-gd

我想在GAE中使用PHP来上传文件图像文件。

在存储之前,我想将每个文件转换为JPEG并将其缩小为缩略图质量。

使用以下代码(在普通PHP环境中完全有效,减去特定于桶的调整),我能够接收上传并确定临时文件名和位置,但getimagesize在尝试访问时会产生错误CloudStorage。

$bucket = CloudStorageTools::getDefaultGoogleStorageBucketName();
$bucketPath = "gs://" . $bucket . "/" . $_SERVER["REQUEST_ID_HASH"] . "/";
$counter = 0;

foreach($_FILES["file"]["name"] as $idx => $tempFile) {
    $counter++;
    $sourceFile = $bucketPath . $tempFile;

    syslog(LOG_DEBUG, $sourceFile);

    $photoInfo = getimagesize($sourceFile);
    if ($photoInfo["mime"] == "image/jpeg") {
        $photoImage = imagecreatefromjpeg($sourceFile);
        $valid = true;
    }
    elseif ($photoInfo["mime"] == "image/gif") {
        $photoImage = imagecreatefromgif($sourceFile);
        $valid = true;
    }
    elseif ($photoInfo["mime"] == "image/png") {
        $photoImage = imagecreatefrompng($sourceFile);
        $valid = true;
    }

    if (isset($valid)) {
        $date = date("Y-m-d H:i:s");

        $photoFolder = rtrim($photoFolder, "/") . "/";
        $photoFile = "Test {$counter} {$date}.jpg";

        $imageSaved = imagejpeg($photoImage, $photoFolder.$photoFile, 50);

        syslog(LOG_DEBUG, "File saved is " . $imageSaved);
    }
}

第一个syslog条目确认文件路径和名称......

gs://[myappid].appspot.com/AC3E3530/IMG_20160701_120144.jpg

错误日志在尝试打开流时显示错误,但我不知道如何解决它。

PHP Warning:  getimagesize(gs://[myappid].appspot.com/AC3E3530/IMG_20160701_120144.jpg): failed to open stream: "\google\appengine\ext\cloud_storage_streams\CloudStorageStreamWrapper::stream_open" call failed in /base/data/home/apps/s~[myappid]/v1.394746390020376247/code/server.php on line 169

我已经在GAE上使用了这个功能的变体,其中包含我的服务器通过Twilio接收的照片(其中processPhoto()是与我上面摘录的代码相同的功能)。在这种情况下,我使用getimagesize和imagecreate与URL。我只是不知道如何使用CloudStorage。

if ($fetch && $numMedia > 0) {
    for ($x = 0; $x < $numMedia; $x++) {
        $sourceFile = $_REQUEST["MediaUrl" . $x];
        $sid = $_REQUEST["MessageSid"];
        processPhoto("sms", $projectID, $sourceFile, $caption, $sid, $mobile, $message);
    }
}

2 个答案:

答案 0 :(得分:2)

我认为问题是临时文件在我处理之前已被删除。所以,我...

  1. 删除了处理多个文件的功能(我 根本不需要)。
  2. 立即将文件移至另一个存储桶。
  3. 检查文件的类型。
  4. 根据需要保存。
  5. 删除临时文件。
  6. 这是我在PHP中生成的表单。没有提交按钮,因为我通过jQuery观察文件更改。

    <form id='form_uploadPhotos' method='post' enctype='multipart/form-data' action='{$websiteURL}?action=uploadPhotos'>
        <input type='file' id='input_uploadPhoto' name='file'>
        <input type='hidden' name='projectID' value='{$projectID}'>
    </form>
    

    这是在提交表单时调用的uploadPhotos函数:

    if ($action == "uploadPhotos") {
        $projectID = preg_replace("/\D/", "", $_REQUEST["projectID"]);
    
        $bucket = CloudStorageTools::getDefaultGoogleStorageBucketName();
        $bucketPath = "gs://" . $bucket . "/" . $_SERVER["REQUEST_ID_HASH"] . "/";
    
        $date = date("Y-m-d H:i:s");
        $time = time();
    
        $photoFile = sprintf("%08d", $projectID) . "." . $date . "." . $time . ".TEMP";
        $sourceFile = $photoFolder.$photoFile; // The default photo folder is defined elsewhere.
    
        move_uploaded_file($_FILES["file"]["tmp_name"], $sourceFile);
        processPhoto("upload", $projectID, $sourceFile, null, null, null, null);
    }
    

    这是处理照片的功能。其他进程也会调用它来接收照片(例如,通过Twilio的SMS附件)。

    function processPhoto($via, $projectID, $sourceFile, $caption, $twilioMessageID, $smsMobile, $smsMessage) {
        global $photoFolder;
    
        $photoInfo = getimagesize($sourceFile);
        if ($photoInfo["mime"] == "image/jpeg") {
            $photoImage = imagecreatefromjpeg($sourceFile);
            $valid = true;
        }
        elseif ($photoInfo["mime"] == "image/gif") {
            $photoImage = imagecreatefromgif($sourceFile);
            $valid = true;
        }
        elseif ($photoInfo["mime"] == "image/png") {
            $photoImage = imagecreatefrompng($sourceFile);
            $valid = true;
        }
    
        if (isset($valid)) {
            $date = date("Y-m-d H:i:s");
            $time = time();
            $photoFile = sprintf("%08d", $projectID) . "." . $date . "." . $time . ".JPEG";
    
            $photoImage = imagecreatefromjpeg($sourceFile);
            list($width, $height) = getimagesize($sourceFile);
            if (max($width, $height) > 800) {
                $scale = 800/max($width, $height);
                $newWidth = floor($width * $scale);
                $newHeight = floor($height * $scale);
                $saveImage = imagecreatetruecolor($newWidth, $newHeight);
                imagecopyresampled($saveImage, $photoImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
            }
    
            $imageSaved = imagejpeg($photoImage, $photoFolder.$photoFile);
            imagedestroy($photoImage);
    
            if ($imageSaved) {
                if (isset($twilioMessageID)) {
                    $twilioMediaID = substr($sourceFile, strrpos($sourceFile, "/") + 1);
                    purgeTwilioMedia($twilioMessageID, $twilioMediaID);
                }
                elseif (substr($sourceFile, strrpos($sourceFile, ".")) == ".TEMP") {
                    unlink($sourceFile);
                }
    
                <Additional processing (e.g., adding entry to database.)
                .
                .
                .
            }
        }
    }
    

    注意:“list($ width,$ height ...”和“imagecopyresampled ...”之间的图像缩放代码基于另一个问题的Dano's answer

答案 1 :(得分:0)

我猜测您正在点击limitation of the Standard Environment标准运行时中的getimagesize原生函数不能使用gs://等文件扩展名网址。