将 PHP getimagesize 和 imagecreate 与 Google App Engine 和 Google Cloud Storage 结合使用
Using PHP getimagesize and imagecreate with Google App Engine and Google Cloud Storage
我想在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);
}
}
第一个系统日志条目确认文件路径和名称...
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);
}
}
我猜您遇到了 limitation of the Standard Environment,其中标准运行时中的 getimagesize
本机函数不适用于 gs://
URL 等文件扩展名。
我认为问题在于临时文件在我可以处理之前被删除了。所以,我...
- 删除了处理多个文件的功能(我
无论如何都不需要)。
- 立即将文件移动到另一个存储桶。
- 检查文件的类型。
- 根据需要保存。
- 删除临时文件。
这是我在 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另一个问题
我想在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);
}
}
第一个系统日志条目确认文件路径和名称...
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);
}
}
我猜您遇到了 limitation of the Standard Environment,其中标准运行时中的 getimagesize
本机函数不适用于 gs://
URL 等文件扩展名。
我认为问题在于临时文件在我可以处理之前被删除了。所以,我...
- 删除了处理多个文件的功能(我 无论如何都不需要)。
- 立即将文件移动到另一个存储桶。
- 检查文件的类型。
- 根据需要保存。
- 删除临时文件。
这是我在 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另一个问题