简体   繁体   中英

Using PHP getimagesize and imagecreate with Google App Engine and Google Cloud Storage

I want to use PHP in GAE to upload file image files.

Before storing, I want to convert each file to JPEG and reduce it to thumbnail quality.

Using the following code (which fully works in a normal PHP environment, less the bucket-specific adjustments), I am able to receive the uploads and determine the temporary file name and location, but getimagesize produces an error when attempting to access the 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);
    }
}

The first syslog entry confirms the file path and name...

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

The error log shows an error in attempting to open the stream, but I don't know how to address it.

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

I already have a variation of this functionality working on GAE with photos that my server receives through Twilio (where processPhoto() is a function identical to the code I excerpted above). In this case, I'm using getimagesize and imagecreate with a URL. I just don't know how to do the same with 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);
    }
}

I think the problem was that the temporary file was removed before I could process it. So, I...

  1. Removed the functionality of processing multiple files (which I didn't need anyhow).
  2. Immediately move the file to another bucket.
  3. Examine the file for its type.
  4. Save it as desired.
  5. Remove the temporary file.

This is the form that I generate in PHP. There's no Submit button because I watch for a file change with 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>

This is the uploadPhotos function that's called when the form is submitted:

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);
}

This is the function that processes the photo. It's called by other processes that also receive photos (eg, SMS attachments via Twilio).

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.)
            .
            .
            .
        }
    }
}

Note: The image scaling code between "list($width, $height..." and "imagecopyresampled..." is based on Dano's answer to another question.

我猜想您遇到了标准环境限制,即标准运行时中的getimagesize本机函数不适用于文件扩展名,例如gs:// URL。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM