Google Cloud Storage filesystem driver for Laravel

Overview

Google Cloud Storage filesystem driver for Laravel

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads


Google Cloud Storage filesystem driver for Laravel.

This started as a fork from Superbalist/laravel-google-cloud-storage. Changes include:

  • Laravel 8 and PHP 8 only support
  • Merging some long overdue PRs
  • Re-wrote the service provider
  • Basically only the readme is left from the fork 🤷

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Installation

You can install the package via composer:

composer require spatie/laravel-google-cloud-storage

Next, add a new disk to your filesystems.php config:

'gcs' => [
    'driver' => 'gcs',
    'key_file_path' => env('GOOGLE_CLOUD_KEY_FILE', null), // optional: /path/to/service-account.json
    '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_BUCKET', 'your-bucket'),
    'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null), // optional: /default/path/to/apply/in/bucket
    'storage_api_uri' => 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
],

Usage

$disk = Storage::disk('gcs');

$disk->put('avatars/1', $fileContents);
$exists = $disk->exists('file.jpg');
$time = $disk->lastModified('file1.jpg');
$disk->copy('old/file1.jpg', 'new/file1.jpg');
$disk->move('old/file1.jpg', 'new/file1.jpg');
$url = $disk->url('folder/my_file.txt');
$url = $disk->temporaryUrl('folder/my_file.txt', now()->addMinutes(30));
$disk->setVisibility('folder/my_file.txt', 'public');

See https://laravel.com/docs/master/filesystem for full list of available functionality.

Authentication

The Google Client uses a few methods to determine how it should authenticate with the Google API.

  1. If you specify a path in the key key_file in disk config, that json credentials file will be used.

  2. If the GOOGLE_APPLICATION_CREDENTIALS env var is set, it will use that.

    putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json');
  3. It will then try load the key file from a 'well known path':

    • windows: %APPDATA%/gcloud/application_default_credentials.json
    • others: $HOME/.config/gcloud/application_default_credentials.json
  4. If running in Google App Engine, the built-in service account associated with the application will be used.

  5. If running in Google Compute Engine, the built-in service account associated with the virtual machine instance will be used.

  6. If you want to authenticate directly without using a json file, you can specify an array for key_file in disk config with this data:

    'key_file' => [
        'type' => env('GOOGLE_CLOUD_ACCOUNT_TYPE'),
        'private_key_id' => env('GOOGLE_CLOUD_PRIVATE_KEY_ID'),
        'private_key' => env('GOOGLE_CLOUD_PRIVATE_KEY'),
        'client_email' => env('GOOGLE_CLOUD_CLIENT_EMAIL'),
        'client_id' => env('GOOGLE_CLOUD_CLIENT_ID'),
        'auth_uri' => env('GOOGLE_CLOUD_AUTH_URI'),
        'token_uri' => env('GOOGLE_CLOUD_TOKEN_URI'),
        'auth_provider_x509_cert_url' => env('GOOGLE_CLOUD_AUTH_PROVIDER_CERT_URL'),
        'client_x509_cert_url' => env('GOOGLE_CLOUD_CLIENT_CERT_URL'),
    ],

Public URLs

The adapter implements a getUrl($path) method which returns a public url to a file.

Note: Method available for Laravel 5.2 and higher. If used on 5.1, it will throw an exception.

$disk = Storage::disk('gcs');
$url = $disk->url('folder/my_file.txt');
// http://storage.googleapis.com/bucket-name/folder/my_file.txt

If you configure a path_prefix in your config:

$disk = Storage::disk('gcs');
$url = $disk->url('folder/my_file.txt');
// http://storage.googleapis.com/bucket-name/path-prefix/folder/my_file.txt

If you configure a custom storage_api_uri in your config:

$disk = Storage::disk('gcs');
$url = $disk->url('folder/my_file.txt');
// http://your-custom-domain.com/bucket-name/path-prefix/folder/my_file.txt

For a custom domain (storage api uri), you will need to configure a CNAME DNS entry pointing to storage.googleapis.com.

Please see https://cloud.google.com/storage/docs/xml-api/reference-uris#cname for further instructions.

Temporary / Signed URLs

With the latest adapter versions, you can easily generate a signed URLs for files that are not publicly visible by default.

$disk = Storage::disk('gcs');
$url = $disk->temporaryUrl('folder/my_file.txt', now()->addMinutes(30));
// https://storage.googleapis.com/test-bucket/folder/my_file.txt?GoogleAccessId=test-bucket%40test-gcp.iam.gserviceaccount.com&Expires=1571151576&Signature=tvxN1OS1txkWAUF0cCR3FWK%seRZXtFu42%04%YZACYL2zFQxA%uwdGEmdO1KgsHR3vBF%I9KaEzPbl4b7ic2IWUuo8Jh3IoZFqdTQec3KypjDtt%02DGwm%OO6pWDVV421Yp4z520%o5oMqGBtV8B3XmjW2PH76P3uID2QY%AlFxn23oE9PBoM2wXr8pDXhMPwZNJ0FtckSc26O8PmfVsG7Jvln%CQTU57IFyB7JnNxz5tQpc2hPTHbCGrcxVPEISvdOamW3I%83OsXr5raaYYBPcuumDnAmrK%cyS9%Ky2fL2B2shFO2cz%KRu79DBPqtnP2Zf1mJWBTwxVUCK2jxEEYcXBXtdOszIvlI6%tp2XfVwYxLNFU

Please see https://cloud.google.com/storage/docs/access-control/signed-urls and https://laravel.com/docs/6.x/filesystem for more info.

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please review our security policy on how to report security vulnerabilities.

Credits

License

The MIT License (MIT). Please see License File for more information.

Comments
  • version 2.0.3 broke google auth

    version 2.0.3 broke google auth

    When I use the latest version of the package (2.0.3) i have the following problem:

    Google\Cloud\Core\Exception\BadRequestException
    <?xml version='1.0' encoding='UTF-8'?><Error><Code>InvalidAuthentication</Code><Message>The provided authentication header is invalid.</Message><Details>Cannot use OAuth Authorization header with form POST.</Details></Error>
    

    When reverting to 2.0.2... all work fine.

    opened by veneliniliev 14
  • Laravel 9.2 Issue

    Laravel 9.2 Issue

    Hi,

    I'm using it in my Laravel 9 project with the following code:

    image

    the put method returns false and no file is created.

    No exception thrown.

    Any help?

    opened by andreladocruz 10
  • metadata not updating after we upload to cloud storage

    metadata not updating after we upload to cloud storage

    Hello,

    We recently used this library for our laravel app. We followed the documentation in order to configure it. We face an issue where, even though we are setting some metadata options, we don't see them implemented on GCS.

    'cdn' => [
                'driver' => 'gcs',
                'project_id' => env('GOOGLE_CDN_PROJECT_ID', 'test'),
                'key_file_path' => base_path(env('GOOGLE_COM_CDN_SERVICE_JSON', 'test.json')), // optional: /path/to/service-account.json
                'bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET', 'test'),
                'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', ''), // optional: /default/path/to/apply/in/bucket
                'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', ''), // see: Public URLs below
                'visibility' => 'public', // optional: public|private
                'metadata' => ['cacheControl' => 'no-cache,max-age:0']
            ]
    

    image

    opened by bairamispanagiotis 6
  • fix incorrect usage of storageApiUri / apiEndpoint config

    fix incorrect usage of storageApiUri / apiEndpoint config

    apiEndpoint was used as both apiEndpoint and storage_api_uri, this commit separates them.

    The storage_api_uri config is used to change the URL of accessing objects, not the API calls.
    ApiEndpoint is used to change the actual rest API endpoint of the storageClient. I have not found a use-case to change the apiEndpoint, but this PR leaves it up to the user to change it or not.

    Fixes #25

    With this PR we're able to use bucketBoundHostnames again by setting the storage_api_uri config:

    'gcs' => [
        'driver' => 'gcs',
        'key_file_path' => env('GOOGLE_CLOUD_KEY_FILE', null), // optional: /path/to/service-account.json
        '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_BUCKET', 'your-bucket'),
        'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', ''), // optional: /default/path/to/apply/in/bucket
        'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', 'https://cdn.example.org'), // see: Public URLs below
        'apiEndpoint' => env('GOOGLE_CLOUD_STORAGE_API_ENDPOINT', null), // set storageClient apiEndpoint
        'visibility' => 'public', // optional: public|private
        'metadata' => ['cacheControl'=> 'public,max-age=86400'], // optional: default metadata
    ],
    

    And generate the correct url() and temporaryUrl() for example: https://cdn.example.org/cats.jpeg instead of https://storage.googleapis.com/your-bucket/cats.jpeg.

    A good default config would be:

    'gcs' => [
        'driver' => 'gcs',
        'key_file_path' => env('GOOGLE_CLOUD_KEY_FILE', null), // optional: /path/to/service-account.json
        '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_BUCKET', 'your-bucket'),
        'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', ''), // optional: /default/path/to/apply/in/bucket
        'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', null), // see: Public URLs below
        'apiEndpoint' => env('GOOGLE_CLOUD_STORAGE_API_ENDPOINT', null), // set storageClient apiEndpoint
        'visibility' => 'public', // optional: public|private
        'metadata' => ['cacheControl'=> 'public,max-age=86400'], // optional: default metadata
    ],
    
    opened by Rkallenkoot 2
  • Cannot get file placement to work

    Cannot get file placement to work

    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?

    opened by matthiastjong 2
  • League\Flysystem\UnableToCheckFileExistence: Unable to check existence for: laravel 9, php 8.1.4

    League\Flysystem\UnableToCheckFileExistence: Unable to check existence for: laravel 9, php 8.1.4

    $path = Storage::exists('slXpLQ7xZ5xnf0Mi3kBSaq.png'); gives below error in laravel 9

    League\Flysystem\UnableToCheckFileExistence: Unable to check existence for: slXpLQ7xZ5xnf0Mi3kBSaq.png in file \vendor\league\flysystem\src\UnableToCheckExistence.php on line 14

    #0 \vendor\league\flysystem-google-cloud-storage\GoogleCloudStorageAdapter.php(76): League\Flysystem\UnableToCheckExistence::forLocation('slXpLQ...', Object(TypeError)) #1 \vendor\league\flysystem\src\Filesystem.php(48): League\Flysystem\GoogleCloudStorage\GoogleCloudStorageAdapter->fileExists('slXpLQ...') #2 \vendor\laravel\framework\src\Illuminate\Filesystem\FilesystemAdapter.php(174): League\Flysystem\Filesystem->has('slXpLQ...') #3 \vendor\laravel\framework\src\Illuminate\Filesystem\FilesystemManager.php(396): Illuminate\Filesystem\FilesystemAdapter->exists('slXpLQ...') #4 \vendor\laravel\framework\src\Illuminate\Support\Facades\Facade.php(337): Illuminate\Filesystem\FilesystemManager->__call('exists', Array) #5 \app\Http\Controllers\AdminSettingController.php(214): Illuminate\Support\Facades\Facade::__callStatic('exists', Array) #6 \vendor\laravel\framework\src\Illuminate\Routing\Controller.php(54): App\Http\Controllers\AdminSettingController->run(Object(Illuminate\Http\Request)) #7 \vendor\laravel\framework\src\Illuminate\Routing\ControllerDispatcher.php(45): Illuminate\Routing\Controller->callAction('run', Array) #8 \vendor\laravel\framework\src\Illuminate\Routing\Route.php(261): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(App\Http\Controllers\AdminSettingController), 'run') #9 \vendor\laravel\framework\src\Illuminate\Routing\Route.php(204): Illuminate\Routing\Route->runController() #10 \vendor\laravel\framework\src\Illuminate\Routing\Router.php(725): Illuminate\Routing\Route->run() #11 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(141): Illuminate\Routing\Router->Illuminate\Routing{closure}(Object(Illuminate\Http\Request)) #12 \vendor\laravel\framework\src\Illuminate\Routing\Middleware\SubstituteBindings.php(50): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #13 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure)) #14 \vendor\laravel\framework\src\Illuminate\Session\Middleware\StartSession.php(121): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #15 \vendor\laravel\framework\src\Illuminate\Session\Middleware\StartSession.php(64): Illuminate\Session\Middleware\StartSession->handleStatefulRequest(Object(Illuminate\Http\Request), Object(Illuminate\Session\Store), Object(Closure)) #16 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Session\Middleware\StartSession->handle(Object(Illuminate\Http\Request), Object(Closure)) #17 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #18 \vendor\laravel\framework\src\Illuminate\Routing\Router.php(727): Illuminate\Pipeline\Pipeline->then(Object(Closure)) #19 \vendor\laravel\framework\src\Illuminate\Routing\Router.php(702): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request)) #20 \vendor\laravel\framework\src\Illuminate\Routing\Router.php(666): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route)) #21 \vendor\laravel\framework\src\Illuminate\Routing\Router.php(655): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request)) #22 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(167): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request)) #23 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(141): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http{closure}(Object(Illuminate\Http\Request)) #24 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #25 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull.php(31): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure)) #26 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull->handle(Object(Illuminate\Http\Request), Object(Closure)) #27 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TransformsRequest.php(21): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #28 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\TrimStrings.php(40): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure)) #29 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\TrimStrings->handle(Object(Illuminate\Http\Request), Object(Closure)) #30 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\ValidatePostSize.php(27): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #31 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure)) #32 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance.php(86): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #33 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance->handle(Object(Illuminate\Http\Request), Object(Closure)) #34 \vendor\fruitcake\laravel-cors\src\HandleCors.php(52): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #35 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Fruitcake\Cors\HandleCors->handle(Object(Illuminate\Http\Request), Object(Closure)) #36 \vendor\laravel\framework\src\Illuminate\Http\Middleware\TrustProxies.php(39): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #37 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(180): Illuminate\Http\Middleware\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure)) #38 \vendor\laravel\framework\src\Illuminate\Pipeline\Pipeline.php(116): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline{closure}(Object(Illuminate\Http\Request)) #39 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(142): Illuminate\Pipeline\Pipeline->then(Object(Closure)) #40 \vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php(111): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request)) #41 \public\index.php(52): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request)) #42 {main}

    opened by kapilsabhaya 2
  • Unable to check existence in Laravel 9

    Unable to check existence in Laravel 9

    League\Flysystem\UnableToCheckFileExistence

    "function": "forLocation", "class": "League\Flysystem\UnableToCheckExistence", "type": "::"

    opened by umang200 2
  • Make getBucket() method public

    Make getBucket() method public

    Make the getBucket() method public, so we can call the generateSignedPostPolicyV4() method on the bucket outside the class: $bucket->generateSignedPostPolicyV4($objectName,$dateTime)

    https://cloud.google.com/storage/docs/xml-api/post-object-forms#php

    opened by maelga 2
  • TypeError: League\Flysystem\GoogleCloudStorage\GoogleCloudStorageAdapter::__construct():

    TypeError: League\Flysystem\GoogleCloudStorage\GoogleCloudStorageAdapter::__construct():

    Hello,

    I just installed the package for Laravel 9 with the following config :

    'gcs' => [ 'driver' => 'gcs', 'key_file_path' => env('GOOGLE_CLOUD_KEY_FILE', null), // optional: /path/to/service-account.json 'key_file' => json_decode(file_get_contents('credentials.json'), true), // 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_BUCKET', 'dev-eu-prioritis-developement'), 'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null), // optional: /default/path/to/apply/in/bucket 'storage_api_uri' => 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 ],

    then I cleared the cache with artisan.

    When I instanciate the storage : $disk = Storage::disk('gcs'); I get this error : TypeError: League\Flysystem\GoogleCloudStorage\GoogleCloudStorageAdapter::__construct(): Argument #2 ($prefix) must be of type string, null given, called in /Users/jeremyaublanc/Prioritis/laravel-prismaccess/vendor/spatie/laravel-google-cloud-storage/src/GoogleCloudStorageServiceProvider.php on line 45

    Could you help me with this ? It seems something goes wrong because construct try to get 'root' field in config file but it doesn't exist.

    Thank you Jeremy

    opened by bouffekai 2
  • Filesystem

    Filesystem

    Is not using the filesystem config properly.... When we set the path_prefix, it's actually ignoring it. Also, when we set the storage_api_url, the bucket url is not correctly formed, as it takes the storage.googleapis.com URL from the images instead of the one we set.

    'products' => [
                'driver'                => 'gcs',
                'key_file_path'         => storage_path('xxx_gae.json'),
                'project_id'            => 'xxxxxxxxxxx',
                'bucket'                => 'static.xxxxxxxxx.com',
                'path_prefix'           => 'dev/products',
                'storage_api_uri'       => 'https://static.xxxxxxxxx.com/',
                'visibility'            => 'public'
            ],
    

    And to get the URL Storage::disk('products')->url($this->image)

    We are getting: https://storage.googleapis.com/static.xxxxxxxxx.com/<img>

    Instead of: https://static.xxxxxxxxx.com/<path_prefix>/<img>

    opened by msalaoniric 2
  • Drive [gcs] is not supported

    Drive [gcs] is not supported

      I've done the composer install and added the section to my filesystem.php and configured my env variables but when I try to upload to it I get a message -
    
    message: "Driver [gcs] is not supported.", exception: "InvalidArgumentException",…}
    exception : "InvalidArgumentException"
    file : "/app/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemManager.php"
    line :  148
    message :  "Driver [gcs] is not supported."
    

    Ay ideas? I've only set the following 2 env variables as it appears all the others are optional.

    GOOGLE_CLOUD_STORAGE_BUCKET=laravel_storage
    GOOGLE_CLOUD_KEY_FILE=/app/360204-c02cb6578b45.json
    

    before you say it my entire Laravel app is in an app folder so this is not the normal Laravel /app folder that folder is found at /app/app.

    Originally posted by @mobreviews in https://github.com/spatie/laravel-google-cloud-storage/discussions/48

    opened by mobreviews 1
  • On-demand disks - not taking into account scoped prefix

    On-demand disks - not taking into account scoped prefix

    Hi there,

    As this is my first ticket, firstly I'd like to thank everyone for maintaining this repository, it helped me out greatly! Second, I think this is a bug from what I can see, so my apologies if I'm incorrect.

    I'm using on-demand disks where you can inject some configuration into the Storage facade, which then builds a disk merging existing filesystem.php configuration with the configuration you add:

     Storage::build([
                'driver' => 'scoped',
                'disk' => 'gcs',
                'prefix' => $path,
            ]);
    

    However, it seems like the Google Cloud Storage adapter does not take into account the "prefix" part of the build configuration. I did some small debugging in the library itself and it looks like indeed, this property is not taken.

    I believe what needs to be done is that in the GoogleCloudStorageServiceProvider - prepareConfig function, the 'prefix' might need to be added as an additional property to check for?

    Edit

    As I dig deeper, it seems like the prepareConfig is only called when the provider is booted, so I think the required changes might need to be done in the createClient function, as that is the one that is being called when calling Storage::build()

    A quick and dirty fix is this, but I think what would be more preferable is that this function can always check for 'root', but currently I lack the deeper knowledge on where that change might best be made as I feel like the "prepareConfig" is called once, and that's where the mapping happens between possible path prefix keys and the "root" property for the FlySystem.

    protected function createAdapter(StorageClient $client, array $config): FlysystemGoogleCloudStorageAdapter
        {
            $bucket = $client->bucket(Arr::get($config, 'bucket'));
    
            $pathPrefix = Arr::get($config, 'prefix') ?? Arr::get($config, 'root');  # This is the only line that changed
            $visibility = Arr::get($config, 'visibility');
            $defaultVisibility = in_array(
                $visibility,
                [
                    Visibility::PRIVATE,
                    Visibility::PUBLIC,
                ]
            ) ? $visibility : Visibility::PRIVATE;
    
            return new FlysystemGoogleCloudStorageAdapter($bucket, $pathPrefix, null, $defaultVisibility);
        }
    
    opened by coreation 0
  • File is not uploaded to bucket, read is possible

    File is not uploaded to bucket, read is possible

    Discussed in https://github.com/spatie/laravel-google-cloud-storage/discussions/29

    Originally posted by souljacker June 24, 2022 I'm running Laravel 9, and just installed the package.

    In my ENV I'm using these vars with the correct data GOOGLE_CLOUD_STORAGE_BUCKET= GOOGLE_CLOUD_KEY_FILE= FILESYSTEM_DISK=gcs

    I can confirm it works because I manually updated a jpeg to the bucket and this returns true: Storage::exists('teste.jpeg');

    If I try for any other filename it returns false, so it's actually reading the bucket.

    Trying to write to the bucket, though, won't work nor return any errors.

    This, does nothing:

    Storage::put('teste.txt', 'asdasdadasddaasd');

    I gave admin access to my service account, so I don't think it's permissions.

    Any ideas?

    opened by souljacker 5
Releases(2.0.5)
  • 2.0.5(Sep 28, 2022)

    What's Changed

    • make prepareConfig method protected instead of private by @Nielsvanpach in https://github.com/spatie/laravel-google-cloud-storage/pull/50

    New Contributors

    • @Nielsvanpach made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/50

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/2.0.4...2.0.5

    Source code(tar.gz)
    Source code(zip)
  • 2.0.4(Sep 24, 2022)

    What's Changed

    • Update README.md by @veneliniliev in https://github.com/spatie/laravel-google-cloud-storage/pull/20
    • Update README.md: Flysystem v2 -> Flysystem v3 by @MohannadNaj in https://github.com/spatie/laravel-google-cloud-storage/pull/26
    • Typo in README by @careybaird in https://github.com/spatie/laravel-google-cloud-storage/pull/33
    • fix incorrect usage of storageApiUri / apiEndpoint config by @Rkallenkoot in https://github.com/spatie/laravel-google-cloud-storage/pull/46

    New Contributors

    • @veneliniliev made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/20
    • @MohannadNaj made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/26
    • @careybaird made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/33
    • @Rkallenkoot made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/46

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/2.0.3...2.0.4

    Source code(tar.gz)
    Source code(zip)
  • 2.0.3(Apr 6, 2022)

    What's Changed

    • Uniform bucket-level access by @ultrono in https://github.com/spatie/laravel-google-cloud-storage/pull/17
    • Fix api endpoint configuration by @hotrush in https://github.com/spatie/laravel-google-cloud-storage/pull/19

    New Contributors

    • @ultrono made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/17
    • @hotrush made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/19

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/2.0.2...2.0.3

    Source code(tar.gz)
    Source code(zip)
  • 2.0.2(Feb 15, 2022)

    What's Changed

    • Updated default value for path_prefix by @gcg in https://github.com/spatie/laravel-google-cloud-storage/pull/8

    New Contributors

    • @gcg made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/8

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/2.0.1...2.0.2

    Source code(tar.gz)
    Source code(zip)
  • 2.0.1(Feb 14, 2022)

    What's Changed

    • Fix testbench dependency in CI by @mmachatschek in https://github.com/spatie/laravel-google-cloud-storage/pull/7
    • Use path prefix for temporary URLs by @mmachatschek in https://github.com/spatie/laravel-google-cloud-storage/pull/6
    • Add fallbacks for path prefix as root by @mmachatschek in https://github.com/spatie/laravel-google-cloud-storage/pull/5

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/2.0.0...2.0.1

    Source code(tar.gz)
    Source code(zip)
  • 2.0.0(Feb 9, 2022)

    What's Changed

    • Laravel 9 Flysystem v3 Adapter by @mmachatschek in https://github.com/spatie/laravel-google-cloud-storage/pull/1

    New Contributors

    • @mmachatschek made their first contribution in https://github.com/spatie/laravel-google-cloud-storage/pull/1

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/1.0.1...2.0.0

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Apr 28, 2022)

    • Add support for copying files with uniform ACLs enabled

    Full Changelog: https://github.com/spatie/laravel-google-cloud-storage/compare/1.0.1...1.1.0

    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Aug 19, 2021)

Owner
Spatie
We create products and courses for the developer community
Spatie
This package provides an integration with FFmpeg for Laravel. Laravel's Filesystem handles the storage of the files.

Laravel FFMpeg This package provides an integration with FFmpeg for Laravel 6.0 and higher. Laravel's Filesystem handles the storage of the files. Lau

Protone Media 1.3k Jan 1, 2023
Flysystem storage with local metadata storage for speed and manageability.

Laravel Filer This project was started to scratch my itch on our growing Laravel site: Metadata for all files is stored in a local repository - Suppor

Nick Vahalik 16 May 23, 2022
Laravel Package - Files to S3 Like Cloud Storage

This is a Laravel package that handles and make easy the upload, overwrite, delete, cdn purge of files and directories on AWS S3 like cloud storages. It supports a form uploaded file (UploadedFile) or a base64 file string

André G. Inocenti Lobo Viana 3 Jun 17, 2022
A filesystem-like repository for storing arbitrary resources.

The Puli Repository Component Latest release: 1.0.0-beta10 PHP >= 5.3.9 The Puli Repository Component provides an API for storing arbitrary resources

Puli 435 Nov 20, 2022
A plugin for Blessing Skin Server that can let you display Google Ads with Google AdSense in the website.

A plugin for Blessing Skin Server that can let you display Google Ads with Google AdSense in the website.

Big_Cake 2 Jan 25, 2022
Orbit is a flat-file driver for Laravel Eloquent

Orbit is a flat-file driver for Laravel Eloquent. It allows you to replace your generic database with real files that you can manipulate using the methods you're familiar with.

Ryan Chandler 664 Dec 30, 2022
A Laravel Broadcast Driver for Centrifugo

Laravel Centrifugo Features Compatible with latest Centrifugo 3.0.3 Contains instructions and configuration file for setting up with Laravel Sail Requ

null 7 Jun 29, 2022
Driver for Laravel Scout search package based on tntsearch

Driver for Laravel Scout search package based on https://github.com/teamtnt/tntsearch

TNT Studio 1k Dec 27, 2022
SingleStore DB Driver for Laravel

SingleStore DB Driver for Laravel This package provides SingleStore specific schema options, currently supporting keys & shard keys, alongside setting

Charlie Joseph 16 Oct 18, 2022
Neo4j Graph Eloquent Driver for Laravel 5.

NeoEloquent Neo4j Graph Eloquent Driver for Laravel 5. Quick Reference Installation Configuration Models Relationships Edges Migration Schema Aggregat

Vinelab 586 Dec 7, 2022
Driver for managing cash payments in the Cashier Provider ecosystem

Cash Driver Provider Installation To get the latest version of Cash Driver Provider, simply require the project using Composer: $ composer require cas

Cashier Provider 4 Aug 30, 2022
Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud Messaging (FCM).

Laravel-FCM Introduction Laravel-FCM is an easy to use package working with both Laravel and Lumen for sending push notification with Firebase Cloud M

Rahul Thapa 2 Oct 16, 2022
Use Laravel's built-in ORM classes to query cloud resources with Steampipe.

Laravel Steampipe Use Laravel's built-in ORM classes to query cloud resources with Steampipe, an open source CLI to instantly query cloud APIs using S

Renoki Co. 13 Nov 8, 2022
Enhance your laravel apps with WhatsApp's Cloud API

Enhance your laravel apps with WhatsApp's Cloud API Use Whatsapp API in your Laravel app! Support us Investing on this package is defintely a good mov

Ricardo Sawir 10 Dec 1, 2022
Laravel-tagmanager - An easier way to add Google Tag Manager to your Laravel application.

Laravel TagManager An easier way to add Google Tag Manager to your Laravel application. Including recommended GTM events support. Requirements Laravel

Label84 16 Nov 23, 2022
Manage self-hosted Google Fonts in Laravel apps

This package makes self-hosting Google Fonts as frictionless as possible for Laravel users. To load fonts in your application, register a Google Fonts embed URL and load it with the @googlefonts Blade directive.

Spatie 386 Dec 19, 2022
Automatically disable Google's FLoC in Laravel apps

Automatically disable Google's FLoC in Laravel apps This package will automatically disable Google's FLoC. Support us We invest a lot of resources int

Spatie 68 Oct 21, 2022
Laravel real-time CRUD using Google Firebase.

Laravel real-time CRUD using Google Firebase.

Fadi Mathlouthi 1 Oct 22, 2021
a Google API v3 wrapper for Laravel 4.x

A Google API v3 wrapper for Laravel 4 This package enables a Laravel flavoured way to manage Google services through its API interface (v3) Installati

null 4 Nov 29, 2022