Создание образа без сохранения его как локального файла

Здесь моя ситуация: я хочу создать изображение с измененным размером jpeg из загруженного пользователем изображения, а затем отправить его на S3 для хранения, но я стараюсь не записывать измененный jpeg на диск, а затем перезагружать его для запроса S3.

Есть ли способ сделать это полностью в памяти, с данными изображения JPEG в формате, сохраненными в переменной?

Ответ 1

Большинство пользователей, использующих 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) );
?>

Надеюсь, что это поможет.

Ответ 2

Как только вы получите 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

Это можно сделать, используя библиотеку 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

Ответ 4

Довольно поздно в игру на этом, но если вы используете библиотеку S3, упомянутую ConroyP и Imagick, вы должны использовать метод putObjectString() вместо putObject() из-за того, что getImageBlob возвращает строку. Пример, который, наконец, работал у меня:

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

Я немного боролся с этим, надеюсь, это помогает кому-то другому!

Ответ 5

Поймите, это старый поток, но я потратил некоторое время, ударяя головой о стену на этом сегодня, и подумал, что возьму свое решение здесь для следующего парня.

Этот метод использует AWS SDK для 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);

Ответ 6

Библиотека Imagemagick позволит вам это сделать. Существует много PHP-оберток, таких как этот вокруг него (там даже пример кода для того, что вы хотите сделать на этой странице;))

Ответ 7

Я сталкиваюсь с той же проблемой, используя хранилище объектов openstack и php-opencloud.

Вот мое решение, которое не использует функцию ob_start и ob_end_clean, но сохраняет изображение в памяти и во временном файле. Размер памяти и файла temp можно адаптировать во время выполнения.

// $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://всегда будет хранить свои данные в памяти, тогда как php://temp будет использовать временный файл, как только объем данных будет достигнут предопределенного предела (по умолчанию это 2 МБ). Местоположение этого временного файла определяется так же, как функция sys_get_temp_dir().

Предел памяти для php://temp можно контролировать с помощью добавления /maxmemory: NN, где NN - это максимальный объем данных для хранения в памяти перед использованием временного файла в байтах.

Ответ 8

Maye, используя GD library.

Существует функция для копирования части изображения и изменения размера. Конечно, частью может быть весь образ, таким образом, вы только измените его размер.

см. imagecopyresampled