這是我的情況 - 我想從用戶上傳的圖像創建一個調整大小的jpeg圖像,然後將其發送到S3進行存儲,但我期望避免將調整大小的jpeg寫入該磁盤,然後重新加載它的S3請求。創建一個圖像而不將其存儲爲本地文件
有沒有辦法在內存中完全做到這一點,圖像數據JPEG格式,保存在一個變量?
這是我的情況 - 我想從用戶上傳的圖像創建一個調整大小的jpeg圖像,然後將其發送到S3進行存儲,但我期望避免將調整大小的jpeg寫入該磁盤,然後重新加載它的S3請求。創建一個圖像而不將其存儲爲本地文件
有沒有辦法在內存中完全做到這一點,圖像數據JPEG格式,保存在一個變量?
Imagemagick庫會讓你做到這一點。有大量的PHP包裝,如this一個附近(甚至example code你想要在該頁上做什麼))
一旦你得到了JPEG內存(使用ImageMagick,GD,或您所選擇的圖形庫),你需要從內存中上傳的對象S3。
許多PHP S3類似乎只支持文件上傳,但在一個似乎Undesigned做什麼我們這裏經過 -
// Manipulate image - assume ImageMagick, so $im is image object
$im = new Imagick();
// Get image source data
$im->readimageblob($image_source);
// Upload an object from a resource (requires size):
$s3->putObject($s3->inputResource($im->getimageblob(), $im->getSize()),
$bucketName, $uploadName, S3::ACL_PUBLIC_READ);
如果您使用GD相反,你可以使用 imagecreatefromstring從流中讀取圖像,但是我不確定是否可以獲得所得對象的大小,如上面的s3->inputResource
所示 - getimagesize返回高度,寬度等,但不返回圖像資源的大小。
這可以使用GD庫和輸出緩衝來完成。我不知道這與其他方法相比有多高效,但它不需要顯式創建文件。
//$image contains the GD image resource you want to store
ob_start();
imagejpeg($image);
$jpeg_file_contents = ob_get_contents();
ob_end_clean();
//now send $jpeg_file_contents to S3
使用PHP大多數人選擇使用ImageMagick或Gd2
我從來沒有用過ImageMagick的; Gd2方法:
<?php
// assuming your uploaded file was 'userFileName'
if (! is_uploaded_file(validateFilePath($_FILES[$userFileName]['tmp_name']))) {
trigger_error('not an uploaded file', E_USER_ERROR);
}
$srcImage = imagecreatefromjpeg($_FILES[$userFileName]['tmp_name']);
// Resize your image (copy from srcImage to dstImage)
imagecopyresampled($dstImage, $srcImage, 0, 0, 0, 0, RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT, imagesx($srcImage), imagesy($srcImage));
// Storing your resized image in a variable
ob_start(); // start a new output buffer
imagejpeg($dstImage, NULL, JPEG_QUALITY);
$resizedJpegData = ob_get_contents();
ob_end_clean(); // stop this output buffer
// free up unused memmory (if images are expected to be large)
unset($srcImage);
unset($dstImage);
// your resized jpeg data is now in $resizedJpegData
// Use your Undesigned method calls to store the data.
// (Many people want to send it as a Hex stream to the DB:)
$dbHandle->storeResizedImage(bin2hex($resizedJpegData));
?>
希望這有助於。
這個遊戲很晚,但如果你使用ConroyP和Imagick提到的S3庫,你應該使用putObjectString()方法代替putObject(),因爲getImageBlob返回一個字符串。終於爲我工作的例子:
$headers = array(
'Content-Type' => 'image/jpeg'
);
$s3->putObjectString($im->getImageBlob(), $bucket, $file_name, S3::ACL_PUBLIC_READ, array(), $headers);
我掙扎了這一點,希望它可以幫助別人!
認識到這是一條古老的線索,但我今天花了一些時間在牆上敲打我的頭,並認爲我會在這裏爲我的下一個傢伙捕捉我的解決方案。
此方法使用AWS SDK for PHP 2和GD進行圖像大小調整(Imagick也可以很容易地使用)。
require_once('vendor/aws/aws-autoloader.php');
use Aws\Common\Aws;
define('AWS_BUCKET', 'your-bucket-name-here');
// Configure AWS factory
$aws = Aws::factory(array(
'key' => 'your-key-here',
'secret' => 'your-secret-here',
'region' => 'your-region-here'
));
// Create reference to S3
$s3 = $aws->get('S3');
$s3->createBucket(array('Bucket' => AWS_BUCKET));
$s3->waitUntilBucketExists(array('Bucket' => AWS_BUCKET));
$s3->registerStreamWrapper();
// Do your GD resizing here (omitted for brevity)
// Capture image stream in output buffer
ob_start();
imagejpeg($imageRes);
$imageFileContents = ob_get_contents();
ob_end_clean();
// Send stream to S3
$context = stream_context_create(
array(
's3' => array(
'ContentType'=> 'image/jpeg'
)
)
);
$s3Stream = fopen('s3://'.AWS_BUCKET.'/'.$filename, 'w', false, $context);
fwrite($s3Stream, $imageFileContents);
fclose($s3Stream);
unset($context, $imageFileContents, $s3Stream);
我遇到同樣的問題,使用openstack object store和php-opencloud庫。
這裏是我的解決方案,這確實不使用的ob_start
和ob_end_clean
功能,但是圖像存儲在內存和臨時文件。 The size of the memory and the temp file may be adapted at runtime。
// $image is a resource created by gd2
var_dump($image); // resource(2) of type (gd)
// we create a resource in memory + temp file
$tmp = fopen('php://temp', '$r+');
// we write the image into our resource
\imagejpeg($image, $tmp);
// the image is now in $tmp, and you can handle it as a stream
// you can, then, upload it as a stream (not tested but mentioned in doc http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html#uploading-from-a-stream)
$s3->putObject(array(
'Bucket' => $bucket,
'Key' => 'data_from_stream.txt',
'Body' => $tmp
));
// or, for the ones who prefers php-opencloud :
$container->createObject([
'name' => 'data_from_stream.txt',
'stream' => \Guzzle\Psr7\stream_for($tmp),
'contentType' => 'image/jpeg'
]);
關於php://temp
(from the official documentation of php):
PHP://存儲器和PHP://溫度是允許的臨時數據被存儲在一個類文件的讀寫流包裝。兩者之間的唯一區別是php://內存將始終將其數據存儲在內存中,而一旦存儲的數據量達到預定義限制(缺省值爲2 MB),php:// temp將使用臨時文件。此臨時文件的位置與sys_get_temp_dir()函數的確定方式相同。
php:// temp的內存限制可以通過追加/ maxmemory:NN來控制,其中NN是使用臨時文件之前保留在內存中的最大數據量,以字節爲單位。
我應該澄清 - 我使用Undesigned的S3類。 你知道GD的做法嗎?在我跳轉到安裝imagemagick之前,很高興知道我是否絕對需要。 – MPX 2008-10-09 22:26:06
我的GD有點粗略 - 我知道你可以像ImageMagick一樣閱讀圖像,雖然不知道如何獲取對象的大小,但自從我瀏覽文檔並且在那裏看不到任何東西的時候已經有一段時間了。 ImageMagick非常值得安裝,儘管IMO! – ConroyP 2008-10-09 22:49:17
imagesx和imagesy返回圖像資源的寬度/高度。 – 2008-10-10 08:19:03