Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用Laravel5.0存储门面向上传到AmazonS3的文件中添加元数据、标题(Expires、CacheControl)_Php_Amazon S3_Laravel 5_Flysystem - Fatal编程技术网

Php 使用Laravel5.0存储门面向上传到AmazonS3的文件中添加元数据、标题(Expires、CacheControl)

Php 使用Laravel5.0存储门面向上传到AmazonS3的文件中添加元数据、标题(Expires、CacheControl),php,amazon-s3,laravel-5,flysystem,Php,Amazon S3,Laravel 5,Flysystem,我正在尝试了解如何将元数据或头(Expires、CacheControl等)添加到使用Laravel 5.0 Storage facade上传的文件中。我把这里的这一页作为参考 以下代码正常工作: Storage::disk('s3')->put('/test.txt', 'test'); 挖掘之后,我还发现有一个“可见性”参数,它将ACL设置为“公共读取”,因此以下内容也可以正常工作 Storage::disk('s3')->put('/test.txt', 'test', '

我正在尝试了解如何将元数据或头(Expires、CacheControl等)添加到使用Laravel 5.0 Storage facade上传的文件中。我把这里的这一页作为参考

以下代码正常工作:

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'));
protected static $metaOptions = [
    'CacheControl',
    'Expires',
    'StorageClass',
    'ServerSideEncryption',
    'Metadata',
    'ACL',
    'ContentType',
    'ContentDisposition',
    'ContentLanguage',
    'ContentEncoding',
];
这不起作用,我也尝试过:

Storage::disk('s3')->put('/index4.txt', 'test', array('ACL'=>'public-read'));
但这会产生一个错误,即“可见性”参数无法从字符串转换为数组。我已经检查了AwsS3Adapter的源代码,似乎有选项代码,但我似乎看不到如何正确地传递它们。我认为需要采取以下措施:

Storage::disk('s3')->put('/index4.txt', 'test', 'public', array('Expires'=>'Expires, Fri, 30 Oct 1998 14:19:41 GMT'));
protected static $metaOptions = [
    'CacheControl',
    'Expires',
    'StorageClass',
    'ServerSideEncryption',
    'Metadata',
    'ACL',
    'ContentType',
    'ContentDisposition',
    'ContentLanguage',
    'ContentEncoding',
];

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

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

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

<?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/filesystems中创建新的fileistem名称

'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适配器


我希望这会对您有所帮助。

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

以你为例:

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

请注意,如果要设置“缓存控制”,则必须将其作为“缓存控制”传递。对于其他非alphanumierc字符的键,这很可能是正确的。

我使用的是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上时,它们都有缓存控制元数据集

为了扩展@sergiodebcn的答案,这里是用于S3V3和最新的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()
    {
        //
    }
}

如果您想使用全局默认的标题,这在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']
],

@Paras的答案是好的。但有一件事会让新来者感到困惑:

'options'     => [
    'Expires' => gmdate('D, d M Y H:i:s GMT', strtotime('+1 month')),
    >>> WRONG visibility' => 'public', WRONG <<<
]
“选项”=>[
'Expires'=>gmdate('D,dm Y H:i:s GMT',strottime('+1个月)),

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

Storage::put(
    'image.jpg',
    file_get_contents($path),
    [
        'visibility' => 'public',
        'Metadata' => [
            'thumb' => '320-180',
        ],
    ]
);
因此,现在如果您在S3中查看新上载的文件,您将看到自定义元数据:


希望这对其他人有所帮助。

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

Storage::disk('s3') -> getDriver() -> put('/index4.txt', 'test', [ 'visibility' => 'public', 'Expires' => 'Expires, Fri, 30 Oct 1998 14:19:41 GMT']);
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中得到了正确的标题。

查看下面的答案()如果您希望在ConfigDriver中设置全局默认值谢谢,没有getDriver()一切都正常直到我需要设置“ContentType”元数据。为什么否决?这个解决方案有效,如果你不相信它有效,想知道你为什么这么认为吗?哇,这应该是最好的答案,但有人无缘无故否决了它。我也不确定为什么否决了它,它在Laravel 5.4中对我非常有效。这是一个工作即使在Laravel 5.8中也是如此。很好,谢谢!谢谢你,我认为它可能被否决了,因为这是一个全局解决方案,而不是每个文件/上传的解决方案。你可能不想将其设置为全局级别。当我问这个问题时,我没有这样做。这根本没有文档记录。