29

我正在尝试找出如何将元数据或标头(Expires、CacheControl 等)添加到使用 Laravel 5.0 存储门面上传的文件中。我已使用此处的页面作为参考。

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

以下代码正常工作:

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

挖掘后,我还发现有一个“可见性”参数将 ACL 设置为“公共读取”,因此以下内容也可以正常工作。

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

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

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

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

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

但这会产生一个错误,即“可见性”参数无法从字符串转换为数组。我检查了 AwsS3Adapter 的来源,似乎有选项代码,但我似乎看不到如何正确传递它们。我认为需要以下几点:

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

任何有关如何实现此目的的帮助将不胜感激。

4

9 回答 9

37

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

所以对于你的例子:

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

请注意,如果您正在设置Cache-Control它必须作为CacheControl. 对于具有非字母数字字符的其他键,这很可能是正确的。

于 2015-05-20T16:36:09.057 回答
26

如果你想拥有全局默认标题,这在 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']
],
于 2017-09-10T21:45:14.793 回答
8

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

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

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

在此处输入图像描述

希望这可以帮助某人。

于 2018-01-22T06:42:41.500 回答
3

@Paras 的回答很好。但是有一件事情会让新手感到困惑:

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

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

'visibility'  => 'public',
'options'     => ['Expires' => gmdate('D, d M Y H:i:s GMT', strtotime('+1 month'))]
于 2018-01-22T06:09:12.700 回答
2

对于 Laravel 9 用户来说,这变得更加容易。你不再需要打电话->getDriver()了。您可以直接将选项传递给put命令。

Storage::disk('s3')->put('/index.txt', 'file content', [
    // S3 Object ACL
    'visibility' => 'public', // or 'private',

    // HTTP Headers
    'CacheControl' => 'public,max-age=315360000',
    'ContentDisposition' => 'attachment; filename="index.txt"',
    'Expires' => 'Thu, 12 Feb 2032 08:24:43 GMT',

    // Metadata or other S3 options
    'MetadataDirective' => 'REPLACE'
    'Metadata' => [
        'Custom-Key' => 'test',
    ],
])

如果您需要其他头文件或选项,请查看 flysystem 源代码以获取所有可用的头文件和选项。

https://github.com/thephpleague/flysystem-aws-s3-v3/blob/master/src/AwsS3Adapter.php#L38

public const AVAILABLE_OPTIONS = [
    'ACL',
    'CacheControl',
    'ContentDisposition',
    'ContentEncoding',
    'ContentLength',
    'ContentType',
    'Expires',
    'GrantFullControl',
    'GrantRead',
    'GrantReadACP',
    'GrantWriteACP',
    'Metadata',
    'MetadataDirective',
    'RequestPayer',
    'SSECustomerAlgorithm',
    'SSECustomerKey',
    'SSECustomerKeyMD5',
    'SSEKMSKeyId',
    'ServerSideEncryption',
    'StorageClass',
    'Tagging',
    'WebsiteRedirectLocation',
];
于 2022-02-14T08:46:09.817 回答
2

这是从 Laravel 5.8 开始如何将带有过期和缓存控制标头的文件上传到 S3 的示例,例如:

Storage::put($directory . '/' . $imageName, 
            $image, [
              'visibility' => 'public',
              'Expires' => gmdate('D, d M Y H:i:s \G\M\T', time() + (60 * 60 * 24 * 7)),
              'CacheControl' => 'max-age=315360000, no-transform, public',
        ]);

另外不要忘记取消选中 Chrome 中的“禁用缓存”复选框,如果你正在测试并且它似乎永远不会工作,这让我很糟糕一个小时,即使我最终得到了正确的标题,我的浏览器也不会缓存东西在 S3 中。

于 2019-07-01T22:40:33.657 回答
1

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

首先,创建一个新文件 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()
{
    //
}
}

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

'App\Providers\CustomS3Filesystem',

在 config/filesystems 中创建新的文件系统名称

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

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

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

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

我希望这可以帮助你。

于 2015-05-15T22:48:43.707 回答
1

为了扩展@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()
    {
        //
    }
}
于 2017-09-05T01:52:00.377 回答
1

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

我的配置文件:

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

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

于 2015-11-17T04:31:32.117 回答