web-dev-qa-db-fra.com

Ajoutez des métadonnées et des en-têtes (Expires, CacheControl) à un fichier téléchargé sur Amazon S3 à l'aide de la commande Laravel 5.0 façade de stockage

J'essaie de savoir comment ajouter des métadonnées ou des en-têtes (Expires, CacheControl, etc.) à un fichier téléchargé à l'aide de la façade Laravel 5.0 Stockage. J'ai utilisé la page ici comme référence.

http://laravel.com/docs/5.0/filesystem

Le code suivant fonctionne correctement:

Storage::disk('s3')->put('/test.txt', 'test');

Après avoir creusé, j'ai également constaté qu'il existait un paramètre de "visibilité" qui définissait la liste de contrôle d'accès sur "lecture publique", de sorte que le texte suivant fonctionne également correctement.

Storage::disk('s3')->put('/test.txt', 'test', 'public');

Mais j'aimerais pouvoir définir d'autres valeurs dans l'en-tête du fichier. J'ai essayé ce qui suit:

Storage::disk('s3')->put('/index4.txt', 'test', 'public', array('Expires'=>'Expires, Fri, 30 Oct 1998 14:19:41 GMT'));

Ce qui ne marche pas, j'ai aussi essayé:

Storage::disk('s3')->put('/index4.txt', 'test', array('ACL'=>'public-read'));

Mais cela crée une erreur où le paramètre "visibilité" ne peut pas être converti d'une chaîne en un tableau. J'ai vérifié la source de AwsS3Adapter et il semble qu'il y ait du code pour les options mais je n'arrive pas à voir comment les transmettre correctement. Je pense qu'il faut ce qui suit:

protected static $metaOptions = [
    'CacheControl',
    'Expires',
    'StorageClass',
    'ServerSideEncryption',
    'Metadata',
    'ACL',
    'ContentType',
    'ContentDisposition',
    'ContentLanguage',
    'ContentEncoding',
];

Toute aide sur la façon d'accomplir ceci serait appréciée.

21
alexmcfarlane

Tout d’abord, vous devez appeler getDriver pour pouvoir envoyer un large éventail d’options. Et ensuite, vous devez envoyer les options sous forme de tableau.

Donc pour votre exemple:

Storage::disk('s3') -> getDriver() -> put('/index4.txt', 'test', [ 'visibility' => 'public', 'Expires' => 'Expires, Fri, 30 Oct 1998 14:19:41 GMT']);

Sachez que si vous définissez 'Cache-Control', il doit être passé comme 'CacheControl'. Cela peut être vrai pour d'autres clés avec des caractères non alphanumériques.

24
Matt McDonald

Si vous voulez avoir des valeurs globales par défaut avec des en-têtes, cela fonctionne dans Laravel 5.4. Changez votre fichier config/filesystems.php comme suit:

s3' => [
    'driver' => 's3',
    'key' => env('AWS_KEY'),
    'secret' => env('AWS_SECRET'),
    'region' => env('AWS_REGION'),
    'bucket' => env('AWS_BUCKET'),
    'options' => ['CacheControl' => 'max-age=315360000, no-transform, public', 
                  'ContentEncoding' => 'gzip']
],
13
Paras

Après avoir tenté les réponses ci-dessus sans avoir pu ajouter les métadonnées de l'utilisateur, il est apparu qu'après avoir fouillé dans le code du SDK, le processus était un peu plus simple que prévu (Assume $path est un chemin d'accès à un fichier image). Je n'ai pas semblé avoir besoin d'appeler la méthode getDriver() non plus, pas vraiment sûr que cela fasse une différence avec la version actuelle du kit SDK AWS.

Storage::put(
    'image.jpg',
    file_get_contents($path),
    [
        'visibility' => 'public',
        'Metadata' => [
            'thumb' => '320-180',
        ],
    ]
);

Alors maintenant, si vous visualisez le fichier récemment téléchargé dans S3, vous verrez les métadonnées personnalisées:

 enter image description here

J'espère que ça aide quelqu'un.

4
XanT

La réponse de @Paras est bonne. Mais il y a une chose qui peut confondre les nouveaux arrivants:

'options'     => [
    'Expires' => gmdate('D, d M Y H:i:s GMT', strtotime('+1 month')),
    >>> WRONG visibility' => 'public', WRONG <<<
]

Si vous souhaitez définir des options globales pour HEADERS, le tableau d’options est la bonne solution. Mais si vous souhaitez également définir la visibilité, vous ne pouvez pas la mélanger. La visibilité doit être définie en dehors du tableau d'options.

????

'visibility'  => 'public',
'options'     => ['Expires' => gmdate('D, d M Y H:i:s GMT', strtotime('+1 month'))]
1

Hey j'ai résolu ce problème, vous devez créer un système de fichiers S3 personnalisé

Tout d’abord, créez un nouveau fichier CustomS3Filesystem.php et enregistrez-le dans app/providers, ce système de fichiers S3 personnalisé utilise l’adaptateur S3, mais vous pouvez ajouter des métadonnées et des en-têtes.

<?php namespace App\Providers;
use Storage;
use League\Flysystem\Filesystem;
use Aws\S3\S3Client;
use League\Flysystem\AwsS3v2\AwsS3Adapter as S3Adapter;
use Illuminate\Support\ServiceProvider;

class CustomS3Filesystem extends ServiceProvider {

public function boot()
{
    Storage::extend('s3_custom', function($app, $config)
    {
        $s3Config = array_only($config, ['key', 'region', 'secret', 'signature', 'base_url']);
        $flysystemConfig = ['mimetype' => 'text/xml'];
        $metadata['cache_control']='max-age=0, no-cache, no-store, must-revalidate';
        return new Filesystem(new S3Adapter(S3Client::factory($s3Config), $config['bucket'], null, ['mimetype' => 'text/xml', 'Metadata' => $metadata]), $flysystemConfig);
    });
}
public function register()
{
    //
}
}

Ajouter un fournisseur à la liste des fournisseurs à config/app.php

'App\Providers\CustomS3Filesystem',

créer un nouveau nom de fichier dans les systèmes de configuration

's3-new' => [
            'driver' => 's3_custom',
            'key'    => 'XXX',
            'secret' => 'XXX',
            'bucket' => 'XXX',
        ],

Utiliser le nouvel adaptateur s3 personnalisé créé

Storage::disk('s3-new')->put(filename, file_get_contents($file), public);

J'ai utilisé la documentation Laravel pour personnaliser l'adaptateur s3 http://laravel.com/docs/5.0/filesystem#custom-filesystems

J'espère que cela peut vous aider.

1
sergiodebcn

Pour développer la réponse de @sergiodebcn, voici la même classe CustomS3Filesystem fonctionnant pour S3 v3 et le dernier Laravel. Remarque J'ai supprimé le type MIME XML et configuré une heure de cache de 5 jours:

namespace App\Providers;

use Illuminate\Support\Arr;
use Storage;
use League\Flysystem\Filesystem;
use Aws\S3\S3Client;
use League\Flysystem\AwsS3v3\AwsS3Adapter as S3Adapter;
use Illuminate\Support\ServiceProvider;

class CustomS3Filesystem extends ServiceProvider
{

    /**
     * Format the given S3 configuration with the default options.
     *
     * @param  array  $config
     * @return array
     */
    protected function formatS3Config(array $config)
    {
        $config += ['version' => 'latest'];

        if ($config['key'] && $config['secret']) {
            $config['credentials'] = Arr::only($config, ['key', 'secret']);
        }

        return $config;
    }

    /**
     * Bootstrap a custom filesystem
     *
     * @return void
     */
    public function boot()
    {
        Storage::extend('s3_custom', function($app, $config)
        {
            $s3Config = $this->formatS3Config($config);
            return new Filesystem(
                new S3Adapter(
                    new S3Client($s3Config),
                    $config['bucket'],
                    null,
                    [
                        'CacheControl'  => 'max-age=432000'
                    ]
                )
            );
        });
    }

    public function register()
    {
        //
    }
}
1
delatbabel

J'utilise Laravel 4.2, mais je pense que ma solution pourrait également aider sur Laravel 5.0 (je ne peux pas dire avec certitude, car je n'ai pas encore essayé de mettre à niveau). Vous devez mettre à jour les méta-options de la configuration pour le pilote Flysystem que vous utilisez. Dans mon cas, j'ai créé une connexion appelée s3static pour accéder au compartiment où je stocke des images qui ne changeront pas. 

Mon fichier de configuration:

's3static' => [
            'driver'     => 'awss3',
            'key'        => 'my-key',
            'secret'     => 'my-secret',
            'bucket'     => 'my-bucket',
            // 'region'     => 'your-region',
            // 'base_url'   => 'your-url',
            'options'    => array(
                'CacheControl' => 'max_age=2592000'
            ),
            // 'prefix'     => 'your-prefix',
            // 'visibility' => 'public',
            // 'eventable'  => true,
            // 'cache'      => 'foo'
        ],

Maintenant, lorsque je mets tous les fichiers sur S3 en utilisant cette connexion, ils disposent du méta-jeu Cache-Control. 

0
Venky Rao