Add Metadata, headers (Expires, CacheControl) to a file uploaded to Amazon S3 using the Laravel 5.0 Storage facade

15,257

Solution 1

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.

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.

Solution 2

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

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

Solution 3

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.

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:

enter image description here

Hope this helps someone.

Solution 4

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

'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.

👍

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

Solution 5

This is an example of how to upload a file to S3 as of Laravel 5.8 with expiry and cache control headers, for example:

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

Also don't forget to uncheck the 'Disable cache' checkbox in Chrome if you're testing and it never seems to work, that got me bad for an hour when my browser wouldn't cache things even though I finally got the headers right in S3.

Share:
15,257
alexmcfarlane
Author by

alexmcfarlane

My background spans full stack development, emerging technologies and technical direction. Specialising in creative innovation I have over a decade of experience conceptualising creative campaigns, website build, API integration, online marketing, social media technologies and mobile.

Updated on June 22, 2022

Comments

  • alexmcfarlane
    alexmcfarlane almost 2 years

    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.

    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.

    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:

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

    Any help on how to accomplish this would be appreciated.