sábado, 7 de noviembre de 2015

Subir un archivos a Amazon S3 con laravel 5.1 (consejos)

Subir un archivo a amazon S3 desde una aplicacion laravel 5.1 es muy sencillo. En este articulo no voy hacer un tutorial paso a paso de como hacerlo, en su lugar voy a dar unos consejos sobre mi experiencia sobre este proceso.

Primero como subir los archivos a amazon S3, los tutoriales que yo seguí para lograrlo son los siguientes:

http://laravelcoding.com/blog/laravel-5-beauty-upload-manager#11-s3-act
http://laravel.io/forum/05-13-2015-storing-user-uploaded-files-on-s3
http://laravel.com/api/5.1/Illuminate/Contracts/Filesystem/Cloud.html#method_put

Si sigues esos tutoriales podrás lograrlo sin problemas. Los siguientes son retos y errores con los que me encontré en el proceso.

1) Error:  AWS HTTP error: cURL error 60: Peer certificate cannot be authenticated with given CA certificates

error image in AWS S3


Una posible explicación a este problema lo podemos encontrar en este link: 


Una cosa muy interesante es que este error solo ocurria en mi versión local con windows. Si subía el código a producción en Heroku funcionaba perfectamente. Las posibles soluciones para este error se listan en este link.


Si no logras solucionar el problema con todos los pasos del link anterior, entonces haz lo siguiente en tu proyecto laravel 5.1

Localiza el siguiente archivo: \vendor\guzzlehttp\ringphp\src\Client\CurlFactory.php 

y busca la linea de codigo: 

$options[CURLOPT_SSL_VERIFYPEER] = true;

Solo necesitas cambiar  el valor a "false". Con esto el problema debería de solucionarse. A mi me ha funcionado en mis pruebas.

2) Las imágenes y archivos subidos a Amazon S3 cambian su content-type

Este problema usualmente lo notas cuando subes una imagen a tu bucket y al visitar el link en el navegador la imagen es descargada y no cargada en el navegador. 

Este comportamiento no ocurre si subes tus archivos de esta manera :

$disk= Storage::disk('s3');
$disk->put($targetFile, file_get_contents($sourceFile));

Pero si en su lugar usas esta técnica descrita en este enlace Upload large files to S3 using Laravel 5:

$disk = Storage::disk('s3');
$disk->put($targetFile, fopen($sourceFile, 'r+'));

Notaras el problema. Aqui un screenshot:



Como puedes notar el content-type fue cambiado a "application/octet-stream".  La solución a este problema esta en los siguientes links:


Lo que necesitamos hacer es forzar el content-type en AWS S3, de la siguiente manera:

Storage::disk('s3') -> getDriver() ->put($targetFile, fopen($sourceFile, 'r+'), ['ContentType' => 'text/css']);

3) Subir images a AWS S3 creadas con imagejpeg() 

Si Estas creando imagenes con PHP y quieres enviarlas a tu bucket S3 sin guardalas en tu disco local primero tienes que hacer lo que describen en este link:


Yo he usado este metodo:

// Capture image stream in output buffer
ob_start();
imagejpeg($dest);
$imageFileContents = ob_get_contents();
ob_end_clean();


Storage::disk('s3') -> getDriver()->put($targetFile,$imageFileContents,[
   'visibility' => 'public',
   'ContentType' => 'image/jpeg'
]);                     
imagedestroy($dest);

Espero haber servido de ayuda a otros con el mismo problema