Source de données : S3


1Présentation

Amazon S3 est un espace de stockage de fichiers, infini et peu onéreux. Temma permet de manipuler facilement les fichiers stockés sur S3, en y accédant comme n'importe quelle autre source de données.

Si vous avez correctement configuré les paramètres de connexion à S3, Temma crée automatiquement un objet de type \Temma\Datasources\S3. Par convention, nous partirons du principe que vous avez nommé cette connexion s3 dans le fichier etc/temma.php (voir la documentation de la configuration).

La connexion est alors disponible dans le contrôleur en écrivant :

$this->s3

Dans les autres objets gérés par le composant d'injection de dépendances, la connexion à S3 est accessible en écrivant :

$loader->dataSources['s3']

2Installation

Pour pouvoir se connecter à AWS (Amazon Web Services), Temma a besoin d'accéder au SDK AWS PHP. Cela peut se faire en l'installant avec Composer, ou en l'installant manuellement.

2.1Installation avec Composer

Pour installer le SDK AWS PHP avec Composer, il suffit de taper cette commande depuis la racine du projet :

$ composer require aws/aws-sdk-php

2.2Installation manuelle

Pour installer le SDK AWS PHP manuellement, il faut télécharger le fichier aws.phar et le placer dans le répertoire lib/ du projet. Par exemple en exécutant la commande suivante :

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

Vous pouvez choisir d'installer le SDK AWS PHP au niveau du système entier, pour ne pas avoir à le réinstaller dans chaque projet. Pour cela, vous n'avez qu'à copier le fichier aws.phar dans un répertoire qui fait partie des chemins d'inclusion, comme par exemple /usr/share/php (au lieu de le mettre dans le répertoire lib/ de votre projet).


3Configuration

Dans le fichier etc/temma.php (voir la documentation de la configuration), vous déclarez le DSN (Data Source Name) qui permet de se connecter à S3.

Le DSN permettant de se connecter à S3 s'écrit de la forme : s3://CLÉ_ACCÈS:CLÉ_PRIVÉE@RÉGION/BUCKET
La clé d'accès et la clé privée sont fournis par AWS.
La région est de la forme "us-east-1", "eu-west-3", "ca-central-1", etc.
Exemple : s3://AKXYZ:PWD@eu-west-1/data.mydomain.com


4Stockage des fichiers sur S3

Par défaut, les fichiers enregistrés par Temma sur Amazon S3 en mode brut ont le type MIME application/octet-stream, avec un accès privé.

À l'enregistrement d'un fichier, il est possible de spécifier un autre type MIME et/ou un droit d'accès public.

Les fichiers enregistrés sur Amazon S3 en mode sérialisé ont toujours le type MIME application/json.


5Appels unifiés

5.1Accès de type tableau

// vérification de l'existence d'un fichier
if (isset($this->s3['path/key1']))
    doSomething();

// lecture de données (désérialisées)
$data = $this->s3['path/key1'];

// écriture de données (sérialisées)
$this->s3['path/key1'] = $value;

// effacement d'un fichier
unset($this->s3['path/key1']);

// nombre de fichiers (attention, potentiellement lent)
$nbr = count($this->s3);

5.2Méthodes générales

// vérification de l'existence d'un fichier
if ($this->s3->isSet('user/1'))
    doSomething();

// effacement de fichier
$this->s3->remove('user/1');

// effacement de plusieurs fichiers
$this->s3->mRemove(['user/1', 'user/2', 'user/3']);

// effacement de fichiers à patir d'un préfixe
$this->s3->clear('user/');

// effacement de tous les fichiers
$this->s3->flush();

5.3Gestion de données complexes sérialisées

// recherche de fichiers à partir d'un préfixe
$users = $this->s3->search('user/');

// recherche de fichiers à partir d'un préfixe,
// avec récupération des données (désérialisées)
$users = $this->s3->search('user/', true);

// lecture de données (désérialisées)
$user = $this->s3->get('user/1');
// lecture de données avec valeur par défaut
$color = $this->s3->get('color', 'blue');
// lecture de données avec création de données si nécessaire
$user = $this->s3->get("user/$userId", function() use ($userId) {
    return $this->dao->get($userId);
});
// lecture de données avec création si nécessaire,
// avec un accès public
$user = $this->s3->get("user/$userId", function() use ($userId) {
    return $this->dao->get($userId);
}, true);

// lecture de plusieurs données (désérialisées)
$users = $this->s3->mGet(['user/1', 'user/2', 'user/3']);

// écriture de données (sérialisées)
$this->s3->set('user/1', $userData);
// écriture de données (sérialisées) avec un accès publique
$this->s3->set('user:1', $userData, true);

// écriture de plusieurs données (sérialisées)
$this->s3->mSet([
    'user/1' => $user1data,
    'user/2' => $user2data,
    'user/3' => $user3data,
]);
// écriture de plusieurs données, avec un accès public
$this->s3->mSet([
    'user/1' => $user1data,
    'user/2' => $user2data,
], true);

5.4Gestion de données brutes

// recherche de clés correspondant à un préfixe
$colors = $this->s3->find('color/');

// recherche de clés à partir d'un préfixe,
// avec récupération des données (brutes)
$colors = $this->s3->find('color/', true);

// lecture de données (brutes)
$html = $this->s3->read('page/home');
// lecture de données avec valeur par défaut
$html = $this->s3->read('page/home',
                        '<html><body><h1>Homepage</h1><body><html>');
// lecture de données avec création de données si nécessaire
$html = $this->s3->read('page/home', function() {
    return file_get_contents('/path/to/homepage.html');
});

// lecture de plusieurs données (brutes)
$pages = $this->s3->mRead(['page/home', 'page/admin', 'page/products']);

// copie d'une donnée dans un fichier local
$this->s3->copyFrom('page/home', '/path/to/newpage.html');
// copie d'une donnée dans un fichier local, avec valeur par défaut
$this->s3->copyFrom('page/home', '/path/to/newpage.html', $defaultHtml);
// copie d'une donnée dans un fichier local,
// avec création de données si nécessaire
$this->s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
});
// copie d'une donnée dans un fichier local,
// avec création de données si nécessaire (avec un type MIME spécifique)
$this->s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
}, 'text/html');
// copie d'une donnée dans un fichier local,
// avec création de données si nécessaire (avec un accès public)
$this->s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
}, true);
// copie d'une donnée dans un fichier local,
// avec création de données si nécessaire (avec un type MIME spécifique
// et un accès public)
$this->s3->copyFrom('page/home', '/path/to/newpage.html', function() {
    return file_get_contents('/path/to/oldpage.html');
}, [
    'public'   => true,
    'mimetype' => 'text/html',
]);

// écriture de données (brutes)
$this->s3->write('user/1', $userData);
// écriture de données (brutes) avec un type MIME spécifique
$this->s3->write('user:1', $userData, 'application/pdf');
// écriture de données (brutes) avec un accès publique
$this->s3->write('user:1', $userData, true);
// écriture de données (brutes) avec un type MIME spécifique
// et un accès publique
$this->s3->write('user:1', $userData, [
    'public'   => true,
    'mimetype' => 'application/pdf',
]);

// écriture de plusieurs données (brutes)
$this->s3->mWrite({
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
    'color/green' => '#00ff00',
]);
// écriture de plusieurs données avec un type MIME spécifique
$this->s3->mWrite({
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
], 'text/plain');
// écriture de plusieurs données avec un accès public
$this->s3->mWrite({
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
], true);
// écriture de plusieurs données avec un type MIME spécifique
// et un accès public
$this->s3->mWrite({
    'color/blue'  => '#0000ff',
    'color/red'   => '#ff0000',
], [
    'public'   => true,
    'mimetype' => 'text/plain',
]);

// écriture d'une donnée (brute) à partir d'un fichier local
$this->s3->copyTo('page/home', '/path/to/homepage.html');
// écriture d'une donnée à partir d'un fichier local, avec un type MIME spécifique
$this->s3->copyTo('page/home', '/path/to/homepage.html', 'text/html');
// écriture d'une donnée à partir d'un fichier local, avec un accès public
$this->s3->copyTo('page/home', '/path/to/homepage.html', true);
// écriture d'une donnée à partir d'un fichier local, avec un type MIME spécifique
// et un accès public
$this->s3->copyTo('page/home', '/path/to/homepage.html', [
    'public'   => true,
    'miemtype' => 'text/html',
]);

// écriture de plusieurs données (brutes) à partir de fichiers locaux
$this->s3->mCopyTo([
    'page/home'     => '/path/to/homepage.html',
    'page/admin'    => '/path/to/admin.html',
    'page/products' => '/path/to/products.html',
]);
// écriture de plusieurs données à partir de fichiers locaux
// avec un type MIME spécifique
$this->s3->mCopyTo([
    'page/home'  => '/path/to/homepage.html',
    'page/admin' => '/path/to/admin.html',
], 'text/html');
// écriture de plusieurs données à partir de fichiers locaux
// avec un accès public
$this->s3->mCopyTo([
    'page/home'  => '/path/to/homepage.html',
    'page/admin' => '/path/to/admin.html',
], true);
// écriture de plusieurs données à partir de fichiers locaux
// avec un type MIME spécifique et un accès public
$this->s3->mCopyTo([
    'page/home'  => '/path/to/homepage.html',
    'page/admin' => '/path/to/admin.html',
], [
    'public'   => true,
    'mimetype' => 'text/html',
]);

6Appels spécifiques

6.1getUrl()

getUrl(string $s3Path) : string

De base, les fichiers stockés sur S3 avec un accès privé ne sont pas accessible aux utilisateurs qui n'ont pas un compte AWS avec les droits d'accès sur le bucket ou sur le fichier lui-même.

Néanmoins, il est possible de créer des URLs temporaires, qui permettent d'accéder aux fichiers pendant un temps déterminé. La méthode getUrl() permet de créer de telles URLs "pré-signées", qui sont valables pendant 20 minutes.

Ces URLs sont utiles pour offrir un accès à des fichiers uniquement aux utilisateurs authentifiés sur le site web.

Exemple :

// récupération de l'URL temporaire
$url = $this->s3->getUrl('documents/report.pdf');

// redirection vers cette URL
$this->_redirect($url);