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

时间:2015-03-11 14:41:32

标签: php amazon-s3 laravel-5 flysystem

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

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

以下代码正常运行:

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

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

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'));

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

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

如何实现这一目标的任何帮助将不胜感激。

8 个答案:

答案 0 :(得分:24)

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

所以对你的例子来说:

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

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

答案 1 :(得分:14)

如果要使用标题的全局默认值,这适用于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']
],

答案 2 :(得分:4)

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

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

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

enter image description here

希望这有助于某人。

答案 3 :(得分: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中创建新的filesistem名称

'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

我希望这对你有所帮助。

答案 4 :(得分:1)

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

$_.bgrp

答案 5 :(得分:1)

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

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

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

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

答案 6 :(得分:1)

这是一个如何从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中的标题。

答案 7 :(得分:0)

我正在使用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元数据集。