这是我的情况 - 我想从用户上传的图像创建一个调整大小的jpeg图像,然后将其发送到S3进行存储,但我希望避免将调整大小的jpeg写入磁盘,然后为S3请求重新加载它
有没有办法在内存中完全执行此操作,图像数据JPEG格式化,保存在变量中?
答案 0 :(得分:12)
大多数使用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( $resizedJpegData );
?>
希望这有帮助。
答案 1 :(得分:7)
这可以使用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
答案 2 :(得分:6)
一旦你在内存中使用了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返回高度,宽度等,但不是图像资源的大小。
答案 3 :(得分:5)
这个游戏的游戏很晚,但是如果你使用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);
我有点挣扎这个,希望它可以帮助别人!
答案 4 :(得分:5)
意识到这是一个古老的线索,但今天我花了一些时间在墙上撞到墙上,并且认为我会在这里为下一个人抓住我的解决方案。
此方法使用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);
答案 5 :(得分:4)
Imagemagick库可以让你这样做。有许多PHP包装器,如this一个(对于你想在该页面上做什么,甚至example code;))
答案 6 :(得分:1)
我遇到了同样的问题,使用openstack对象存储和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:// memory和php:// temp是读写流,允许临时数据存储在类似文件的包装器中。两者之间的唯一区别是php://内存将始终将其数据存储在内存中,而一旦存储的数据量达到预定义的限制(默认值为2 MB),php:// temp将使用临时文件。此临时文件的位置以与sys_get_temp_dir()函数相同的方式确定。
可以通过附加/ maxmemory:NN来控制php:// temp的内存限制,其中NN是在使用临时文件之前要保留在内存中的最大数据量(以字节为单位)。
答案 7 :(得分:-1)