spatie / laravel-google-cloud-storage

Google Cloud Storage filesystem driver for Laravel
https://spatie.be/open-source
MIT License
196 stars 51 forks source link

Cannot get file placement to work #24

Closed matthiastjong closed 2 years ago

matthiastjong commented 2 years ago

When I run:

Storage::disk('local')->put('testphoto.png', file_get_contents('https://example.com/photo.png')

The method returns true and the file get placed in my local storage directory.

When I try to use the GCS driver (i called it images) I get this Exception:

Storage::disk('images')->put('testphoto.png', file_get_contents('https://example.com/photo.png')
League \ Flysystem\ UnableToWriteFile

Unable to write file at location: testphoto.png.

This is my configuration in filesystems.php:

'images' => [
            'driver' => 'gcs',
            'key_file_path' => env('GOOGLE_CLOUD_IMAGES_KEY_FILE', null),
            'key_file' => [], // optional: Array of data that substitutes the .json file (see below)
            'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'your-project-id'), // optional: is included in key file
            'bucket' => env('GOOGLE_CLOUD_STORAGE_IMAGES_BUCKET', 'your-bucket'),
            'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', ''), // optional: /default/path/to/apply/in/bucket
            'apiEndpoint' => env('GOOGLE_CLOUD_STORAGE_API_URI', null), // see: Public URLs below
            'visibility' => 'public', // optional: public|private
            'metadata' => ['cacheControl'=> 'public,max-age=86400'], // optional: default metadata
            'throw' => true,
        ],

The error is thrown in League \ Flysystem \ GoogleCloudStorage \ GoogleCloudStorageAdapter: 156 when running $this->bucket->upload($contents, $options); but there is no Exception explaining why the file cannot be written.

Making this into an issue because I ran the exact same code in another Laravel 8.40 environment with version 1.0 of the spatie/laravel-google-cloud-storage package and it worked on that environment (using the GCS key config from the example below).

So for me the problem exists on Laravel 9 with the most recent version of the package.

What did I miss?

matthiastjong commented 2 years ago

Diving further into the code (catching the GCS output) I get this Exception:

{ "error": { "code": 400, "message": "Cannot insert legacy ACL for an object when uniform bucket-level access is enabled. Read more at https://cloud.google.com/storage/docs/uniform-bucket-level-access", "errors": [ { "message": "Cannot insert legacy ACL for an object

When uncommenting line 141 in the GoogleCloudStorageAdapter, it works:

Screenshot 2022-04-13 at 21 34 07

Is there a way to disable the $options['predefinedAcl'] = $predefinedAcl;?

matthiastjong commented 2 years ago

I have found that changing the 'visibility' to this (according to the README) has fixed the problem:

'images' => [
            'driver' => env('IMAGES_DRIVER', 'local'), // use IMAGES_DRIVER=gcs for Google Cloud Storage
            'key_file_path' => env('GOOGLE_CLOUD_IMAGES_KEY_FILE'),
            'key_file' => [],
            'project_id' => env('GOOGLE_CLOUD_PROJECT_ID'),
            'bucket' => env('GOOGLE_CLOUD_STORAGE_IMAGES_BUCKET'),
            'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null),
            'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', null),
            'visibility' => PortableVisibilityHandler::NO_PREDEFINED_VISIBILITY,
            'metadata' => ['cacheControl'=> 'public,max-age=86400'],
            'root' => storage_path('app/public'),
            'url' => env('APP_URL') . '/storage',
            'throw' => true,
        ],