Fuente de datos: S3


1Presentación

Amazon S3 es un espacio de almacenamiento de archivos económico e infinito. Temma facilita la manipulación de archivos almacenados en S3, accediendo a ellos como a cualquier otra fuente de datos.

Si has configurado correctamente los parámetros de conexión a S3, Temma crea automáticamente un objeto de tipo \Temma\Datasources\S3. Por convención, supondremos que has llamado a esta conexión s3 en el archivo etc/temma.php (consulta la documentación de configuración).

La conexión está entonces disponible en el controlador escribiendo:

$s3 = $this->s3;

En otros objetos gestionados por el componente de inyección de dependencias, la conexión a S3 es accesible escribiendo:

$s3 = $loader->dataSources->s3;
$s3 = $loader->dataSources['s3'];

2Instalación

Para conectarse a AWS (Amazon Web Services), Temma necesita acceso al SDK de PHP de AWS. Esto se puede hacer instalándolo con Composer, o instalándolo manualmente.


2.1Instalación con Composer

Para instalar el SDK de PHP de AWS con Composer, basta con escribir este comando desde la raíz del proyecto:

$ composer require aws/aws-sdk-php

2.2Instalación manual

Para instalar el SDK de PHP de AWS manualmente, descarga el archivo aws.phar y colócalo en el directorio lib/ del proyecto. Por ejemplo, ejecutando el siguiente comando:

$ wget -O lib/aws.phar https://docs.aws.amazon.com/aws-sdk-php/v3/download/aws.phar

También puedes optar por instalar el SDK de PHP de AWS a nivel de sistema, para no tener que reinstalarlo en cada proyecto. Para ello, basta con copiar el archivo aws.phar en un directorio que forme parte de las rutas de inclusión, como /usr/share/php (en lugar de colocarlo en el directorio lib/ de tu proyecto).


3Configuración

En el archivo etc/temma.php (consulta la documentación de configuración), declaras el DSN (Data Source Name) usado para conectarte a S3.

El DSN usado para conectarse a S3 se escribe como: s3://ACCESS_KEY:PRIVATE_KEY@REGION/BUCKET
La clave de acceso y la clave privada las proporciona AWS.
La región tiene la forma "us-east-1", "eu-west-3", "ca-central-1", etc.
Ejemplo: s3://AKXYZ:PWD@eu-west-1/data.mydomain.com


4Almacenamiento de archivos en S3

Por defecto, los archivos registrados por Temma en Amazon S3 en modo bruto tienen el tipo MIME application/octet-stream, con acceso privado.

Cuando se registra un archivo, es posible especificar otro tipo MIME y/o un derecho de acceso público.

Los archivos guardados en Amazon S3 en modo serializado siempre tienen el tipo MIME application/json.


5Llamadas unificadas

5.1Acceso tipo array

// verificación de la existencia del archivo
if (isset($s3['path/key1']))
    doSomething();

// leer archivo (deserializado)
$data = $s3['path/key1'];

// escribir archivo (serializado)
$s3['path/key1'] = $value;

// eliminar archivo
unset($s3['path/key1']);

// contar archivos
$cnt = count($s3);

5.2Métodos generales

// verificación de la existencia del archivo
if ($s3->isSet('user/1'))
    doSomething();

// eliminar archivo
$s3->remove('user/1');

// eliminar varios archivos
$s3->mRemove(['user/1', 'user/2', 'user/3']);

// eliminar archivos a partir de un prefijo
$s3->clear('user/');

// eliminar todos los archivos
$s3->flush();

5.3Gestión de datos serializados complejos

// buscar archivos a partir de un prefijo
$users = $s3->search('user/');

// buscar archivos a partir de un prefijo, con recuperación de datos
// (deserializados)
$users = $s3->search('user/', true);

// búsqueda paginada (10 resultados a partir del vigésimo)
$users = $s3->search('user/', true, 20, 10);

// leer archivo (deserializado)
$user = $s3->get('user/1');
// leer archivo con valor por defecto
$color = $s3->get('color', 'blue');
// leer archivo con creación de archivo si es necesario
$user = $s3->get("user/$userId", function() use ($userId) {
    return $this->dao->get($userId);
});
// leer archivo con creación de archivo si es necesario,
// con acceso público
$user = $s3->get("user/$userId", function() use ($userId) {
    return $this->dao->get($userId);
}, true);

// leer varios archivos (deserializados)
$users = $s3->mGet(['user/1', 'user/2', 'user/3']);

// escribir archivo (serializado)
$s3->set('user/1', $userData);
// escribir archivo (serializado) con acceso público
$s3->set('user/1', $userData, true);

// escribir varios archivos (serializados)
$s3->mSet([
    'user/1' => $user1data,
    'user/2' => $user2data,
    'user/3' => $user3data,
]);
// escribir varios archivos, con acceso público
$s3->mSet([
    'user/1' => $user1data,
    'user/2' => $user2data,
], true);

5.4Gestión de datos en bruto

// buscar archivos a partir de un prefijo
$colors = $s3->find('color/');

// buscar archivos a partir de un prefijo, con recuperación de datos (en bruto)
$colors = $s3->find('color/', true);

// búsqueda paginada (10 resultados a partir del vigésimo)
$colors = $s3->find('color/', true, 20, 10);

// leer archivo (en bruto)
$html = $s3->read('page/home');
// leer archivo con valor por defecto
$html = $s3->read('page/home',
                        '<html><body><h1>Homepage</h1><body><html>');
// leer archivo con creación de archivo si es necesario
$html = $s3->read('page/home', function() {
    return file_get_contents('/path/to/homepage.html');
});

// leer varios archivos (en bruto)
$pages = $s3->mRead(['page/home', 'page/admin', 'page/products']);

// copiar un dato en un archivo local
$s3->copyFrom('page/home', '/path/to/newpage.html');
// copiar datos en un archivo local, con valor por defecto
$s3->copyFrom('page/home', '/path/to/newpage.html', $defaultHtml);
// copiar datos en un archivo local, con creación de datos si es necesario
$s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
});
// copiar datos en un archivo local, con creación de datos
// si es necesario (con un tipo MIME específico)
$s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
}, 'text/html');
// copiar datos en un archivo local, con creación de datos
// si es necesario (con acceso público)
$s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
}, true);
// copiar datos en un archivo local, con creación de datos
// si es necesario (con un tipo MIME específico y acceso público)
$s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
}, [
    'public'   => true,
    'mimetype' => 'text/html',
]);

// escribir archivo (en bruto)
$s3->write('user/1', $userData);
// escribir archivo (en bruto) con un tipo MIME específico
$s3->write('user/1', $userData, 'application/pdf');
// escribir archivo (en bruto) con acceso público
$s3->write('user/1', $userData, true);
// escribir archivo (en bruto) con un tipo MIME específico
// y acceso público
$s3->write('user/1', $userData, [
    'public'   => true,
    'mimetype' => 'application/pdf',
]);

// escribir varios archivos (en bruto)
$s3->mWrite([
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
    'color/green' => '#00ff00',
]);
// escribir varios archivos con un tipo MIME específico
$s3->mWrite([
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
], 'text/plain');
// escribir varios archivos con acceso público
$s3->mWrite([
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
], true);
// escribir varios archivos con un tipo MIME específico
// y acceso público
$s3->mWrite([
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
], [
    'public'   => true,
    'mimetype' => 'text/plain',
]);

// escribir archivo (en bruto) a partir de un archivo local
$s3->copyTo('page/home', '/path/to/homepage.html');
// escribir archivo (en bruto) a partir de un archivo local, con un tipo MIME específico
$s3->copyTo('page/home', '/path/to/homepage.html', 'text/html');
// escribir archivo (en bruto) a partir de un archivo local, con acceso público
$s3->copyTo('page/home', '/path/to/homepage.html', true);
// escribir archivo (en bruto) a partir de un archivo local, con un tipo MIME específico
// y acceso público
$s3->copyTo('page/home', '/path/to/homepage.html', [
    'public'   => true,
    'mimetype' => 'text/html',
]);

// escribir varios archivos (en bruto) a partir de archivos locales
$s3->mCopyTo([
    'page/home'     => '/path/to/homepage.html',
    'page/admin'    => '/path/to/admin.html',
    'page/products' => '/path/to/products.html',
]);
// escribir varios archivos a partir de archivos locales con un tipo MIME específico
$s3->mCopyTo([
    'page/home'  => '/path/to/homepage.html',
    'page/admin' => '/path/to/admin.html',
], 'text/html');
// escribir varios archivos a partir de archivos locales con acceso público
$s3->mCopyTo([
    'page/home'  => '/path/to/homepage.html',
    'page/admin' => '/path/to/admin.html',
], true);
// escribir varios archivos a partir de archivos locales, con un tipo MIME específico
// y acceso público
$s3->mCopyTo([
    'page/home'  => '/path/to/homepage.html',
    'page/admin' => '/path/to/admin.html',
], [
    'public'   => true,
    'mimetype' => 'text/html',
]);

6Llamadas específicas

6.1getUrl()

getUrl(string $s3Path) : string

Básicamente, los archivos almacenados en S3 con acceso privado no son accesibles para los usuarios que no tienen una cuenta de AWS con derechos de acceso al bucket o al archivo en sí.

Sin embargo, es posible crear URLs temporales, que permiten acceder a los archivos durante un periodo de tiempo determinado. El método getUrl() se puede usar para crear este tipo de URLs "pre-firmadas", válidas durante 20 minutos.

Estas URLs son útiles para ofrecer acceso a los archivos únicamente a los usuarios autenticados en el sitio web.

Ejemplo:

// recuperar la URL temporal
$url = $s3->getUrl('documents/report.pdf');

// redirección a esta URL
$this->_redirect($url);