Coder Social home page Coder Social logo

flysystem-gcs's Introduction

flysystem-gcs - Flysystem Adapter for Google Cloud Storage

build status

Flysystem Adapter for Google cloud storage using the gcloud PHP library

Installation

Using composer:

composer require cedricziel/flysystem-gcs

How-To

use CedricZiel\FlysystemGcs\GoogleCloudStorageAdapter;
use League\Flysystem\Filesystem;

$adapterOptions = [
    'projectId' => 'my-project-id',
    'bucket'    => 'my-project-bucket.appspot.com',
    'prefix'    => 'my-path-prefix/inside/the/bucket',
];
$adapter = new GoogleCloudStorageAdapter(null, $adapterOptions);

$filesystem = new Filesystem($adapter);

Authentication

This library utilizes the PHP library google/cloud, which in turn uses google/auth.

Why is this important? It's important, because if you're authenticated locally, through the gcloud command-line utility, or running on a Google Cloud Platform VM, in many cases you are already authenticated, and you don't need to do anything at all, in regards to authentication.

For any other case, you will most probably want to export the environment variable GOOGLE_APPLICATION_CREDENTIALS with a value of the absolute path to your service account credentials that is authorized to use the Storage: Full Access oAuth2 scope, and you're all set.

All examples, including tests, make use of this behaviour.

If that's not what you want, you can create your own StorageClient object that's authenticated differently and pass it to the adapter class constructor as first argument.

Demo

There's a demo project that shows simple operations in a file system manager.

Public URLs to StorageObjects

The Adapter ships with 2 different methods to generate public URLs:

  • a flysystem plugin that exposes a getUrl($path) method on your FilesystemInterface instance
  • a getUrl($path) method on the adapter itself to generate the URL

Read below to know when you will want to use the one or the other.

Flysystem Plugin

The standard way to generate public urls with this adapter would be to add a flysystem plugin to your FilesystemInterface instance.

The plugins needs a piece of configuration, telling it whether and which bucket to use in combination with the standard accessible https://storage.googleapis.com/bucket/object.url, or with a custom CNAME URL such as http://storage.my-domain.com.

Notice that GCS public access via CNAMEs is http only (no https).

Example: Standard public URL to bucket

Supposed you have a bucket my-application-bucket, configure the plugin as follows:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(..);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['bucket' => 'my-application-bucket'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'https://storage.googleapis.com/my-application-bucket/text-object.txt';

Example: Standard public URL to bucket with directory prefix

Supposed you have a bucket my-application-bucket with a directory prefix of my/prefix, append the prefix separated by a slash to the bucket name:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(null, ['prefix' => 'my/prefix', ...]);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['bucket' => 'my-application-bucket/my/prefix'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'https://storage.googleapis.com/my-application-bucket/my/prefix/text-object.txt';

Example: Custom domain to bucket

Supposed you have setup a CNAME assets.example.com pointing to the public endpoint mentioned in the documentation, you would configure the plugin as follows:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(..);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['url' => 'http://assets.example.com'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'http://assets.example.com/text-object.txt'

Example: Custom domain to bucket with directory prefix

Supposed you have setup a CNAME assets.example.com pointing to the public endpoint mentioned in the documentation, and your filesystem uses a directory prefix of my/prefix you need to append the prefix to the url in the configuration and would configure the plugin as follows:

// create your adapter as usual
$adapter = new GoogleCloudStorageAdapter(null, ['prefix' => 'my/prefix', ...]);
// add it to your `FilesystemInterface` instance
$filesystem = new Filesystem($adapter);

// create your configuration
$path = 'text-object.txt';
$config = ['url' => 'http://assets.example.com/my/prefix'];
$filesystem->addPlugin(new GoogleCloudStoragePublicUrlPlugin($config));
$publicUrl = $filesystem->getUrl($path);

// $publicUrl == 'http://assets.example.com/my/prefix/text-object.txt'

getUrl on the adapter / Laravel 5

The Storage services used in Laravel 5 do not use flysystem plugins.

The Laravel 5 specific flysystem instance checks if there's a getUrl method on the adapter object.

This method is implemented on the Adapter, which is why you can add the adapter directly and use it right away:

// create the adapter
Storage::extend('gcs', function($app, $config) {
    $adapter = new GoogleCloudStorageAdapter(null, ['bucket' => 'my-bucket', ...]);
    // add it to your `FilesystemInterface` instance
    return new Filesystem($adapter);
});

// register a new disk of type 'gcs' and name it 'gcs'

// use it
$gcs = Storage::disk('gcs');
$path = 'test-laravel.txt';
$gcs->put($path, 'test-content', AdapterInterface::VISIBILITY_PUBLIC);

$publicUrl = $gcs->url($path);
// $publicUrl == 'https://storage.googleapis.com/my-application-bucket/test-laravel.txt';

Development

Some tests require actual access to GCS. They can be configured through the environment.

variable meaning
GOOGLE_APPLICATION_CREDENTIALS absolute path to the service account credentials *.json file
GOOGLE_CLOUD_BUCKET name of the GCS bucket to perform the tests on
GOOGLE_CLOUD_PROJECT the cloud project id to use

Code Style

You can use PHP-CS-Fixer to format the code:

# install fixer
$ composer install --working-dir=tools/php-cs-fixer

# execute fixer
$ tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --allow-risky=yes

License

MIT

flysystem-gcs's People

Contributors

cedricziel avatar daohoangson avatar emilv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

flysystem-gcs's Issues

`getUrl($path)` prints incorrect URL when prefix is defined in config

Having the prefix defined in config causes getUrl($path) to print it twice

$config = [
    'bucket' => 'mybucket',
    'prefix' => 'icon',
];

$adapater = new GoogleCloudStorageAdapter(null, $config);
$adapter->getUrl('test.txt');
// expected: https://storage.googleapis.com/mybucket/icon/test.txt
// actual:   https://storage.googleapis.com/mybucket/icon//icon/test.txt

This is probably because prepareBaseUrl() includes the prefix when it shouldn't.

Undefined index: contentType in GoogleCloudStorageAdapter.php line 473

We get the following error when calling Storage::disk('gcs')->listContents('ftp/pyramid'):

In GoogleCloudStorageAdapter.php line 473:

  [ErrorException]
  Undefined index: contentType


Exception trace:
 Illuminate\Foundation\Bootstrap\HandleExceptions->handleError() at /var/www/aroma-pos/vendor/cedricziel/flysystem-gcs/src/GoogleCloudStorageAdapter.php:473
 CedricZiel\FlysystemGcs\GoogleCloudStorageAdapter->convertObjectInfo() at /var/www/aroma-pos/vendor/cedricziel/flysystem-gcs/src/GoogleCloudStorageAdapter.php:334
 CedricZiel\FlysystemGcs\GoogleCloudStorageAdapter->listContents() at /var/www/aroma-pos/vendor/league/flysystem/src/Filesystem.php:271
 League\Flysystem\Filesystem->listContents() at n/a:n/a
 call_user_func_array() at /var/www/aroma-pos/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php:682
 Illuminate\Filesystem\FilesystemAdapter->__call() at /var/www/aroma-pos/app/Console/Commands/ImportFromPyramid.php:102
 App\Console\Commands\ImportFromPyramid->initFileList() at /var/www/aroma-pos/app/Console/Commands/ImportFromPyramid.php:84

skarmdump 2018-01-26t09 54 16

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.