12

这是我的情况 - 我想从用户上传的图像创建一个调整大小的 jpeg 图像,然后将其发送到 S3 进行存储,但我希望避免将调整大小的 jpeg 写入磁盘,然后为 S3 请求重新加载它。

有没有办法在内存中完全做到这一点,图像数据 JPEG 格式,保存在变量中?

4

8 回答 8

12

大多数使用 PHP 的人选择ImageMagickGd2

我从未使用过 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 );
?>

希望这可以帮助。

于 2009-01-01T01:00:06.977 回答
8

这可以使用 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
于 2009-01-01T00:38:56.443 回答
6

在内存中获得 JPEG 后(使用ImageMagickGD或您选择的图形库),您需要将对象从内存上传到 S3。

许多 PHP S3 类似乎只支持文件上传,但Undesign中的类似乎做了我们在这里所追求的 -

// 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返回高度、宽度、等,但不是图像资源的大小。

于 2008-10-09T22:15:47.503 回答
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);

我在这方面有点挣扎,希望它可以帮助别人!

于 2012-06-27T02:21:13.863 回答
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);
于 2013-10-12T14:11:04.237 回答
4

Imagemagick 库可以让你做到这一点。有很多像这样的 PHP 包装器(甚至还有你想要在该页面上执行的示例代码;))

于 2008-10-09T22:05:25.480 回答
1

我遇到了同样的问题,使用 openstack 对象存储和php-opencloud库。

这是我的解决方案,它不使用andob_start函数ob_end_clean,而是将图像存储在内存和临时文件中。内存和临时文件的大小可以在运行时进行调整

// $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来自php的官方文档):

php://memory 和 php://temp 是读写流,允许将临时数据存储在类似文件的包装器中。两者之间的唯一区别是 php://memory 将始终将其数据存储在内存中,而 php://temp 将在存储的数据量达到预定义限制(默认为 2 MB)时使用临时文件。此临时文件的位置的确定方式与 sys_get_temp_dir() 函数相同。

php://temp 的内存限制可以通过附加 /maxmemory:NN 来控制,其中 NN 是在使用临时文件之前要保留在内存中的最大数据量,以字节为单位。

于 2017-09-01T21:58:01.850 回答
-1

Maye 通过使用GD 库

有一个功能可以复制图像的一部分并调整其大小。当然,这部分可以是整个图像,这样你就只能调整它的大小。

图像复制重新采样

于 2008-10-09T22:09:33.913 回答