创建图像而不将其存储为本地文件

发布于 2024-07-06 06:52:46 字数 147 浏览 7 评论 0原文

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

有没有办法完全在内存中完成此操作,并将图像数据 JPEG 格式保存在变量中?

Here's my situation - I want to create a resized jpeg image from a user uploaded image, and then send it to S3 for storage, but am looking to avoid writing the resized jpeg to the disk and then reloading it for the S3 request.

Is there a way to do this completely in memory, with the image data JPEG formatted, saved in a variable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

z祗昰~ 2024-07-13 06:52:46

大多数使用 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 );
?>

希望这会有所帮助。

Most people using PHP choose either ImageMagick or Gd2

I've never used Imagemagick; the Gd2 method:

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

Hope this helps.

つ低調成傷 2024-07-13 06:52:46

这可以使用 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

This can be done using the GD library and output buffering. I don't know how efficient this is compared with other methods, but it doesn't require explicit creation of files.

//$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
你没皮卡萌 2024-07-13 06:52:46

将 JPEG 存入内存后(使用 ImageMagickGD,或您选择的图形库),您需要将对象从内存上传到 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 返回高度、宽度等,但不返回图像资源的大小。

Once you've got the JPEG in memory (using ImageMagick, GD, or your graphic library of choice), you'll need to upload the object from memory to S3.

Many PHP S3 classes seem to only support file uploads, but the one at Undesigned seems to do what we're after here -

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

If you're using GD instead, you can use
imagecreatefromstring to read an image in from a stream, but I'm not sure whether you can get the size of the resulting object, as required by s3->inputResource above - getimagesize returns the height, width, etc, but not the size of the image resource.

贪恋 2024-07-13 06:52:46

这个游戏已经很晚了,但如果您使用 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);

我在这个问题上遇到了一点困难,希望它对其他人有帮助!

Pretty late to the game on this one, but if you are using the the S3 library mentioned by ConroyP and Imagick you should use the putObjectString() method instead of putObject() due the fact getImageBlob returns a string. Example that finally worked for me:

$headers = array(
    'Content-Type' => 'image/jpeg'
);
$s3->putObjectString($im->getImageBlob(), $bucket, $file_name, S3::ACL_PUBLIC_READ, array(), $headers);

I struggled with this one a bit, hopefully it helps someone else!

吝吻 2024-07-13 06:52:46

意识到这是一个旧线程,但今天我花了一些时间在这个问题上用头撞墙,并认为我会在这里为下一个人捕获我的解决方案。

此方法使用 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);

Realize this is an old thread, but I spent some time banging my head against the wall on this today, and thought I would capture my solution here for the next guy.

This method uses AWS SDK for PHP 2 and GD for the image resize (Imagick could also be easily used).

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);
难得心□动 2024-07-13 06:52:46

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

The Imagemagick library will let you do that. There are plenty of PHP wrappers like this one around for it (there's even example code for what you want to do on that page ;) )

眼泪都笑了 2024-07-13 06:52:46

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

这是我的解决方案,它使用ob_startob_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() 函数相同。

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

I encounter the same problem, using openstack object store and php-opencloud library.

Here is my solution, which does not use the ob_start and ob_end_clean function, but store the image in memory and in temp file. 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'
]);

About php://temp (from the official documentation of php):

php://memory and php://temp are read-write streams that allow temporary data to be stored in a file-like wrapper. The only difference between the two is that php://memory will always store its data in memory, whereas php://temp will use a temporary file once the amount of data stored hits a predefined limit (the default is 2 MB). The location of this temporary file is determined in the same way as the sys_get_temp_dir() function.

The memory limit of php://temp can be controlled by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes.

情释 2024-07-13 06:52:46

Maye 使用 GD 库

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

请参阅 imagecopyresampled

Maye by using the GD library.

There is a function to copy out a part of an image and resize it. Of course the part could be the whole image, that way you would only resize it.

see imagecopyresampled

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文