使用Laravel 5.0 Storage Facade将元数据,标题(Expires,CacheControl)添加到上传到Amazon S3的文件中

时间:2022-07-24 23:03:24

I am trying to find out how to add in Metadata or headers (Expires, CacheControl etc.) to a file uploaded using the Laravel 5.0 Storage facade. I have use the page here as reference.

我试图找出如何将元数据或标题(Expires,CacheControl等)添加到使用Laravel 5.0存储外观上传的文件中。我在这里使用这个页面作为参考。

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

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

The following code works correctly:

以下代码正常工作:

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

After digging I also found that there is a 'visibility' parameter which sets the ACL to 'public-read' so the following also works correctly.

在挖掘之后我还发现有一个'visibility'参数可以将ACL设置为'public-read',因此以下也可以正常工作。

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

But I would like to be able to set some other values to the header of the file. I have tried the following:

但我希望能够为文件的标题设置一些其他值。我尝试过以下方法:

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

Which doesn't work, I have also tried:

哪个不起作用,我也尝试过:

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

But that creates an error where the 'visibility' parameter can not be converted from a string to an array. I have checked the source of AwsS3Adapter and it seems there is code for options but I can not seem to see how to pass them correctly. I think it takes the following:

但是这会产生一个错误,其中'visibility'参数无法从字符串转换为数组。我已经检查了AwsS3Adapter的来源,似乎有选项代码,但我似乎无法看到如何正确传递它们。我认为它需要以下内容:

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

Any help on how to accomplish this would be appreciated.

任何有关如何实现这一点的帮助将不胜感激。

7 个解决方案

#1


24  

First, you need to call getDriver so you can send over an array of options. And then you need to send the options as an array.

首先,您需要调用getDriver,以便发送一系列选项。然后你需要将选项作为数组发送。

So for your example:

所以对你的例子:

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

Be aware that if you're setting 'Cache-Control' it has to be passed as 'CacheControl'. This may well be true for other keys with non-alphanumierc characters.

请注意,如果您正在设置“Cache-Control”,则必须将其作为“CacheControl”传递。对于具有非alphanumierc字符的其他键,这可能是正确的。

#2


13  

If you want to have global defaults with headers, this works in Laravel 5.4. Change your config/filesystems.php file like so:

如果您想要包含标题的全局默认值,这适用于Laravel 5.4。像这样更改config / filesystems.php文件:

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']
],

#3


1  

Hey I solved this problem, you need to create a custom S3 filesystem

嘿我解决了这个问题,你需要创建一个自定义的S3文件系统

First, create a new file CustomS3Filesystem.php and save into app/providers, this custom S3 filesystem uses the S3 Adapter, but you can add metadata and headers.

首先,创建一个新文件CustomS3Filesystem.php并保存到app / providers中,这个自定义S3文件系统使用S3 Adapter,但您可以添加元数据和标头。

<?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()
{
    //
}
}

Add provider into providers list at config/app.php

在config / app.php中将提供者添加到提供者列表中

'App\Providers\CustomS3Filesystem',

create new filesistem name in config/filesystems

在config / filesystems中创建新的filesistem名称

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

Use the new created custom s3 adapter

使用新创建的自定义s3适配器

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

I used laravel documentation to customize the s3 adapter http://laravel.com/docs/5.0/filesystem#custom-filesystems

我使用laravel文档来定制s3适配器http://laravel.com/docs/5.0/filesystem#custom-filesystems

I hope this may help you.

我希望这可以帮到你。

#4


1  

To expand on @sergiodebcn 's answer, here is the same CustomS3Filesystem class working for S3 v3 and the latest Laravel. Note I have removed the XML mimetype and set up a 5 day cache time:

为了扩展@sergiodebcn的答案,这里是适用于S3 v3和最新Laravel的CustomS3Filesystem类。注意我删除了XML mimetype并设置了5天的缓存时间:

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()
    {
        //
    }
}

#5


1  

The answer from @Paras is good. But there is one thing that can confuse newcommers:

@Paras的答案很好。但有一件事可能会让新手们感到困惑:

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

If you want to define global options for the HEADERS, the options array is the right way to go. But if you also want to define the visibility, you can not mix it up. Visibility has to be define outside of options array.

如果要为HEADERS定义全局选项,则选项数组是正确的方法。但是,如果您还想定义可见性,则无法将其混淆。必须在options数组之外定义可见性。

????

????

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

#6


1  

After attempting the above answers and failing to be able to add customer user-metadata it turns out that after digging through the SDK code it is a bit easier than I thought (Assume $path is a path to an image file). I didn't appear to need to call the getDriver() method either, not too sure if that makes any difference with the current version of the AWS SDK.

在尝试上述答案并且无法添加客户用户元数据之后,事实证明在挖掘SDK代码之后它比我想象的要容易一些(假设$ path是图像文件的路径)。我似乎也不需要调用getDriver()方法,不太确定是否与当前版本的AWS SDK有任何区别。

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

So now if you view the newly uploaded file in S3 you will see the custom metadata:

现在,如果您在S3中查看新上传的文件,您将看到自定义元数据:

使用Laravel 5.0 Storage Facade将元数据,标题(Expires,CacheControl)添加到上传到Amazon S3的文件中

Hope this helps someone.

希望这有助于某人。

#7


0  

I am using Laravel 4.2, but I think my solution might also help on Laravel 5.0 (cannot say for sure, as I have not tried to upgrade yet). You need to update the meta options in the config for the Flysystem driver that you are using. In my case, I created a connection called s3static to access the bucket where I am storing images that will not be changing.

我使用的是Laravel 4.2,但我认为我的解决方案也可能对Laravel 5.0有所帮助(不能肯定,因为我还没有尝试升级)。您需要更新正在使用的Flysystem驱动程序的配置中的元选项。在我的例子中,我创建了一个名为s3static的连接来访问存储器,我将存储不会改变的图像。

My config file:

我的配置文件:

'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'
        ],

Now when I put any files on to S3 using this connection, they have the Cache-Control meta data set.

现在,当我使用此连接将任何文件放入S3时,它们具有Cache-Control元数据集。

#1


24  

First, you need to call getDriver so you can send over an array of options. And then you need to send the options as an array.

首先,您需要调用getDriver,以便发送一系列选项。然后你需要将选项作为数组发送。

So for your example:

所以对你的例子:

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

Be aware that if you're setting 'Cache-Control' it has to be passed as 'CacheControl'. This may well be true for other keys with non-alphanumierc characters.

请注意,如果您正在设置“Cache-Control”,则必须将其作为“CacheControl”传递。对于具有非alphanumierc字符的其他键,这可能是正确的。

#2


13  

If you want to have global defaults with headers, this works in Laravel 5.4. Change your config/filesystems.php file like so:

如果您想要包含标题的全局默认值,这适用于Laravel 5.4。像这样更改config / filesystems.php文件:

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']
],

#3


1  

Hey I solved this problem, you need to create a custom S3 filesystem

嘿我解决了这个问题,你需要创建一个自定义的S3文件系统

First, create a new file CustomS3Filesystem.php and save into app/providers, this custom S3 filesystem uses the S3 Adapter, but you can add metadata and headers.

首先,创建一个新文件CustomS3Filesystem.php并保存到app / providers中,这个自定义S3文件系统使用S3 Adapter,但您可以添加元数据和标头。

<?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()
{
    //
}
}

Add provider into providers list at config/app.php

在config / app.php中将提供者添加到提供者列表中

'App\Providers\CustomS3Filesystem',

create new filesistem name in config/filesystems

在config / filesystems中创建新的filesistem名称

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

Use the new created custom s3 adapter

使用新创建的自定义s3适配器

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

I used laravel documentation to customize the s3 adapter http://laravel.com/docs/5.0/filesystem#custom-filesystems

我使用laravel文档来定制s3适配器http://laravel.com/docs/5.0/filesystem#custom-filesystems

I hope this may help you.

我希望这可以帮到你。

#4


1  

To expand on @sergiodebcn 's answer, here is the same CustomS3Filesystem class working for S3 v3 and the latest Laravel. Note I have removed the XML mimetype and set up a 5 day cache time:

为了扩展@sergiodebcn的答案,这里是适用于S3 v3和最新Laravel的CustomS3Filesystem类。注意我删除了XML mimetype并设置了5天的缓存时间:

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()
    {
        //
    }
}

#5


1  

The answer from @Paras is good. But there is one thing that can confuse newcommers:

@Paras的答案很好。但有一件事可能会让新手们感到困惑:

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

If you want to define global options for the HEADERS, the options array is the right way to go. But if you also want to define the visibility, you can not mix it up. Visibility has to be define outside of options array.

如果要为HEADERS定义全局选项,则选项数组是正确的方法。但是,如果您还想定义可见性,则无法将其混淆。必须在options数组之外定义可见性。

????

????

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

#6


1  

After attempting the above answers and failing to be able to add customer user-metadata it turns out that after digging through the SDK code it is a bit easier than I thought (Assume $path is a path to an image file). I didn't appear to need to call the getDriver() method either, not too sure if that makes any difference with the current version of the AWS SDK.

在尝试上述答案并且无法添加客户用户元数据之后,事实证明在挖掘SDK代码之后它比我想象的要容易一些(假设$ path是图像文件的路径)。我似乎也不需要调用getDriver()方法,不太确定是否与当前版本的AWS SDK有任何区别。

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

So now if you view the newly uploaded file in S3 you will see the custom metadata:

现在,如果您在S3中查看新上传的文件,您将看到自定义元数据:

使用Laravel 5.0 Storage Facade将元数据,标题(Expires,CacheControl)添加到上传到Amazon S3的文件中

Hope this helps someone.

希望这有助于某人。

#7


0  

I am using Laravel 4.2, but I think my solution might also help on Laravel 5.0 (cannot say for sure, as I have not tried to upgrade yet). You need to update the meta options in the config for the Flysystem driver that you are using. In my case, I created a connection called s3static to access the bucket where I am storing images that will not be changing.

我使用的是Laravel 4.2,但我认为我的解决方案也可能对Laravel 5.0有所帮助(不能肯定,因为我还没有尝试升级)。您需要更新正在使用的Flysystem驱动程序的配置中的元选项。在我的例子中,我创建了一个名为s3static的连接来访问存储器,我将存储不会改变的图像。

My config file:

我的配置文件:

'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'
        ],

Now when I put any files on to S3 using this connection, they have the Cache-Control meta data set.

现在,当我使用此连接将任何文件放入S3时,它们具有Cache-Control元数据集。