2008-10-09 15 views
11

Aquí está mi situación: quiero crear una imagen jpeg redimensionada desde una imagen cargada por el usuario, y luego enviarla a S3 para su almacenamiento, pero estoy buscando evitar escribir el jpeg redimensionado a el disco y luego volver a cargarlo para la solicitud S3.Crear una imagen sin almacenarla como un archivo local

¿Hay alguna manera de hacerlo completamente en la memoria, con los datos de imagen JPEG formateados, guardados en una variable?

Respuesta

4

La biblioteca Imagemagick le permitirá hacer eso. Hay un montón de envoltorios de PHP como this uno alrededor de él (incluso hay example code para lo que quiere hacer en esa página;))

-1

Maye utilizando el GD library.

Hay una función para copiar una parte de una imagen y cambiar su tamaño. Por supuesto, la parte podría ser la imagen completa, de esa manera solo la redimensionaría.

ver imagecopyresampled

6

Una vez que tenga el archivo JPEG en la memoria (usando ImageMagick, GD, o en su biblioteca gráfica de elección), que tendrá que cargar el objeto de la memoria a S3.

Muchas clases PHP S3 parecen sólo la carga de archivos de apoyo, pero el uno en Undesigned parece hacer lo que estamos buscando aquí -

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

Si está utilizando GD lugar, puede utilizar imagecreatefromstring para leer una imagen desde una secuencia, pero no estoy seguro de si puede obtener el tamaño del objeto resultante, como se requiere en s3->inputResource anterior - getimagesize devuelve la altura, el ancho, etc., pero no el tamaño del recurso de imagen.

+0

Debería haber aclarado: estoy usando la clase S3 de Undesigned. ¿Conoces una forma GD de hacer lo que publicaste arriba? Antes de saltar a la instalación de imagemagick, sería bueno saber si es absolutamente necesario. – MPX

+0

Mi GD es un poco incompleto, sé que se puede leer la imagen de manera similar a ImageMagick, aunque no estoy seguro de obtener el tamaño del objeto, hace un tiempo que revisé los documentos y no pude ver nada allí. ImageMagick bien vale la pena la instalación a través de IMO! – ConroyP

+0

imagesx e imagesy devuelve el ancho/alto de un recurso de imagen. –

6

Esto se puede hacer usando la biblioteca GD y el buffer de salida. No sé qué tan eficiente es esto en comparación con otros métodos, pero no requiere la creación explícita de archivos.

//$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 
11

La mayoría de las personas que utilizan PHP elegir entre ImageMagick o Gd2

nunca he utilizado Imagemagick; el método 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)); 
?> 

Espero que esto ayude.

5

Bastante tarde para el juego en este caso, pero si está utilizando la biblioteca S3 mencionada por ConroyP e Imagick debe usar el método putObjectString() en lugar de putObject() debido a que getImageBlob devuelve una cadena. Ejemplo que finalmente funcionó para mí:

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

Luché con este un poco, ¡espero que ayude a alguien más!

+0

He estado luchando con esto por más de 3 meses y vi algo de luz cuando lo leí. Sin embargo, esto no funciona para mí. 'getImageBlob' parece devolver una cadena vacía mientras' writeImage' funciona en el disco. ¿Alguna idea? – John

+0

Me gusta esta biblioteca s3, es pequeña y simple. Sin embargo, no soportaba carpetas s3 por lo que pude ver. – Matt

5

Date cuenta de que este es un hilo antiguo, pero he pasado un tiempo golpeando mi cabeza contra la pared en esto hoy, y pensé que capturaría mi solución aquí para el siguiente tipo.

Este método usa AWS SDK for PHP 2 y GD para el cambio de tamaño de la imagen (Imagick también se puede usar fácilmente).

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); 
+0

Esto funciona perfectamente, gracias Bart. ¿Hay algún objeto de respuesta que pueda usar para averiguar si la transacción falló? – Matt

+0

Según PHP Docs (http://us2.php.net/manual/en/function.fwrite.php), fwrite devolverá falso por error. – Bart

0

I se produce el mismo problema, usando openstack almacén de objetos y php-opencloud biblioteca.

Aquí está mi solución, que hace no utilizar la función ob_start y ob_end_clean, pero almacenar la imagen en la memoria y en el archivo temporal. 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' 
]); 

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

php: // memoria y php: // temp son corrientes de lectura-escritura que permiten a los datos temporales se almacenen en un archivo similar envoltura. La única diferencia entre los dos es que la memoria php: // siempre almacenará sus datos en la memoria, mientras que php: // temp usará un archivo temporal una vez que la cantidad de datos almacenados alcance un límite predefinido (el valor predeterminado es 2 MB). La ubicación de este archivo temporal se determina de la misma manera que la función sys_get_temp_dir().

El límite de memoria de php: // temp se puede controlar al agregar/maxmemory: NN, donde NN es la cantidad máxima de datos que se debe mantener en la memoria antes de usar un archivo temporal, en bytes.

Cuestiones relacionadas