Kadang-kadang menjadi sangat sulit untuk melakukan tugas-tugas yang terlihat mudah, misalnya menuangkan air dari kendi favorit Anda ke gelas bisa menjadi sangat salah.
Selalu ada teknik atau cara berbeda untuk melakukan tugas sehari-hari seperti hari ini kami akan menambahkan GCS ke Laravel Lumen.
Jadi, hal pertama yang pertama, kita harus memiliki dependensi berikut dalam file composer.json aplikasi kita :
“google / cloud-storage”: “~ 1.0”
“illuminate / filesystem”: “5.1 | 5.2 | 5.3”
“illuminate / support”: "5.1 | 5.2 | 5.3"
"liga / sistem terbang": "1.0"
Secara default, lumen tidak dilengkapi dengan file filesystem.php jadi Anda perlu menambahkannya di folder config:
<?php
return [
/*
|--------------------------------------------------------------------------
| Default Filesystem Disk
|--------------------------------------------------------------------------
|
| Here you may specify the default filesystem disk that should be used
| by the framework. A "local" driver, as well as a variety of cloud
| based drivers are available for your choosing. Just store away!
|
| Supported: "local", "ftp", "s3", "rackspace"
|
*/
'default' => 'local',
/*
|--------------------------------------------------------------------------
| Default Cloud Filesystem Disk
|--------------------------------------------------------------------------
|
| Many applications store files both locally and in the cloud. For this
| reason, you may specify a default "cloud" driver here. This driver
| will be bound as the Cloud disk implementation in the container.
|
*/
'cloud' => 's3',
/*
|--------------------------------------------------------------------------
| Filesystem Disks
|--------------------------------------------------------------------------
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options.
|
*/
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'visibility' => 'public',
],
'gcs' => [
'driver' => 'gcs',
'project_id' => env( 'GOOGLE_CLOUD_PROJECT_ID', 'your-project-id' ),
'key_file' => env( 'GOOGLE_CLOUD_KEY_FILE', null ), // optional: /path/to/service-account.json
'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
],
],
];
Setelah addin g filesystem config untuk aplikasi Anda, Anda perlu menambahkan dua file lebih, satu adalah penyedia Layanan Penyimpanan Google dan juga akan berisi path ke Anda berkas Google Jasa Token yang akan kita bahas nanti dan file kedua adalah Google Storage Adapter yang akan masuk ke folder app \ Adapters ( buat folder jika tidak ada ).
<?php
namespace App\Adapters;
use Google\Cloud\Core\Exception\NotFoundException;
use Google\Cloud\Storage\Acl;
use Google\Cloud\Storage\Bucket;
use Google\Cloud\Storage\StorageClient;
use Google\Cloud\Storage\StorageObject;
use GuzzleHttp\Psr7\StreamWrapper;
use League\Flysystem\Adapter\AbstractAdapter;
use League\Flysystem\AdapterInterface;
use League\Flysystem\Config;
use League\Flysystem\Util;
class GoogleStorageAdapter extends AbstractAdapter
{
/**
* @const STORAGE_API_URI_DEFAULT
*/
const STORAGE_API_URI_DEFAULT = 'https://storage.googleapis.com';
/**
* @var StorageClient
*/
protected $storageClient;
/**
* @var Bucket
*/
protected $bucket;
/**
* @var string
*/
protected $storageApiUri;
/**
* @param StorageClient $storageClient
* @param Bucket $bucket
* @param string $pathPrefix
* @param string $storageApiUri
*/
public function __construct( StorageClient $storageClient, Bucket $bucket, $pathPrefix = null, $storageApiUri = null )
{
$this->storageClient = $storageClient;
$this->bucket = $bucket;
if ( $pathPrefix ) {
$this->setPathPrefix( $pathPrefix );
}
$this->storageApiUri = ( $storageApiUri ) ?: self::STORAGE_API_URI_DEFAULT;
}
/**
* Returns the StorageClient.
*
* @return StorageClient
*/
public function getStorageClient()
{
return $this->storageClient;
}
/**
* Return the Bucket.
*
* @return \Google\Cloud\Storage\Bucket
*/
public function getBucket()
{
return $this->bucket;
}
/**
* Set the storage api uri.
*
* @param string $uri
*/
public function setStorageApiUri( $uri )
{
$this->storageApiUri = $uri;
}
/**
* Return the storage api uri.
*
* @return string
*/
public function getStorageApiUri()
{
return $this->storageApiUri;
}
/**
* {@inheritdoc}
*/
public function write( $path, $contents, Config $config )
{
return $this->upload( $path, $contents, $config );
}
/**
* {@inheritdoc}
*/
public function writeStream( $path, $resource, Config $config )
{
return $this->upload( $path, $resource, $config );
}
/**
* {@inheritdoc}
*
* @codeCoverageIgnore
*/
public function update( $path, $contents, Config $config )
{
return $this->upload( $path, $contents, $config );
}
/**
* {@inheritdoc}
*
* @codeCoverageIgnore
*/
public function updateStream( $path, $resource, Config $config )
{
return $this->upload( $path, $resource, $config );
}
/**
* Returns an array of options from the config.
*
* @param Config $config
*
* @return array
*/
protected function getOptionsFromConfig( Config $config )
{
$options = [];
if ( $visibility = $config->get( 'visibility' ) ) {
$options['predefinedAcl'] = $this->getPredefinedAclForVisibility( $visibility );
} else {
// if a file is created without an acl, it isn't accessible via the console
// we therefore default to private
$options['predefinedAcl'] = $this->getPredefinedAclForVisibility( AdapterInterface::VISIBILITY_PRIVATE );
}
if ( $metadata = $config->get( 'metadata' ) ) {
$options['metadata'] = $metadata;
}
return $options;
}
/**
* Uploads a file to the Google Cloud Storage service.
*
* @param string $path
* @param string|resource $contents
* @param Config $config
*
* @return array
*/
protected function upload( $path, $contents, Config $config )
{
$path = $this->applyPathPrefix( $path );
$options = $this->getOptionsFromConfig( $config );
$options['name'] = $path;
$object = $this->bucket->upload( $contents, $options );
return $this->normaliseObject( $object );
}
/**
* Returns a dictionary of object metadata from an object.
*
* @param StorageObject $object
*
* @return array
*/
protected function normaliseObject( StorageObject $object )
{
$name = $this->removePathPrefix( $object->name() );
$info = $object->info();
$isDir = substr( $name, -1 ) === '/';
if ( $isDir ) {
$name = rtrim( $name, '/' );
}
return [
'type' => $isDir ? 'dir' : 'file',
'dirname' => Util::dirname( $name ),
'path' => $name,
'timestamp' => strtotime( $info['updated'] ),
'mimetype' => isset( $info['contentType'] ) ? $info['contentType'] : '',
'size' => $info['size'],
];
}
/**
* {@inheritdoc}
*/
public function rename( $path, $newpath )
{
if ( ! $this->copy( $path, $newpath ) ) {
return false;
}
return $this->delete( $path );
}
/**
* {@inheritdoc}
*/
public function copy( $path, $newpath )
{
$newpath = $this->applyPathPrefix( $newpath );
// we want the new file to have the same visibility as the original file
$visibility = $this->getRawVisibility( $path );
$options = [
'name' => $newpath,
'predefinedAcl' => $this->getPredefinedAclForVisibility( $visibility ),
];
$this->getObject( $path )->copy( $this->bucket, $options );
return true;
}
/**
* {@inheritdoc}
*/
public function delete( $path )
{
$this->getObject( $path )->delete();
return true;
}
/**
* {@inheritdoc}
*/
public function deleteDir( $dirname )
{
return $this->delete( $this->normaliseDirName( $dirname ) );
}
/**
* {@inheritdoc}
*/
public function createDir( $dirname, Config $config )
{
return $this->upload( $this->normaliseDirName( $dirname ), '', $config );
}
/**
* Returns a normalised directory name from the given path.
*
* @param string $dirname
*
* @return string
*/
protected function normaliseDirName( $dirname )
{
return rtrim( $dirname, '/' ) . '/';
}
/**
* {@inheritdoc}
*/
public function setVisibility( $path, $visibility )
{
$object = $this->getObject( $path );
if ( $visibility === AdapterInterface::VISIBILITY_PRIVATE ) {
$object->acl()->delete( 'allUsers' );
} else if ( $visibility === AdapterInterface::VISIBILITY_PUBLIC ) {
$object->acl()->add( 'allUsers', Acl::ROLE_READER );
}
$normalised = $this->normaliseObject( $object );
$normalised['visibility'] = $visibility;
return $normalised;
}
/**
* {@inheritdoc}
*/
public function has( $path )
{
return $this->getObject( $path )->exists();
}
/**
* {@inheritdoc}
*/
public function read( $path )
{
$object = $this->getObject( $path );
$contents = $object->downloadAsString();
$data = $this->normaliseObject( $object );
$data['contents'] = $contents;
return $data;
}
/**
* {@inheritdoc}
*/
public function readStream( $path )
{
$object = $this->getObject( $path );
$data = $this->normaliseObject( $object );
$data['stream'] = StreamWrapper::getResource( $object->downloadAsStream() );
return $data;
}
/**
* {@inheritdoc}
*/
public function listContents( $directory = '', $recursive = false )
{
$directory = $this->applyPathPrefix( $directory );
$objects = $this->bucket->objects( [ 'prefix' => $directory ] );
$normalised = [];
foreach ( $objects as $object ) {
$normalised[] = $this->normaliseObject( $object );
}
return Util::emulateDirectories( $normalised );
}
/**
* {@inheritdoc}
*/
public function getMetadata( $path )
{
$object = $this->getObject( $path );
return $this->normaliseObject( $object );
}
/**
* {@inheritdoc}
*/
public function getSize( $path )
{
return $this->getMetadata( $path );
}
/**
* {@inheritdoc}
*/
public function getMimetype( $path )
{
return $this->getMetadata( $path );
}
/**
* {@inheritdoc}
*/
public function getTimestamp( $path )
{
return $this->getMetadata( $path );
}
/**
* {@inheritdoc}
*/
public function getVisibility( $path )
{
return [
'visibility' => $this->getRawVisibility( $path ),
];
}
/**
* Return a public url to a file.
*
* Note: The file must have `AdapterInterface::VISIBILITY_PUBLIC` visibility.
*
* @param string $path
*
* @return string
*/
public function getUrl( $path )
{
$uri = rtrim( $this->storageApiUri, '/' );
$path = $this->applyPathPrefix( $path );
// Only prepend bucket name if no custom storage uri specified
// Default: "https://storage.googleapis.com/{my_bucket}/{path_prefix}"
// Custom: "https://example.com/{path_prefix}"
if ( $this->getStorageApiUri() === self::STORAGE_API_URI_DEFAULT ) {
$path = $this->bucket->name() . '/' . $path;
}
return $uri . '/' . $path;
}
/**
* @param string $path
*
* @return string
*/
protected function getRawVisibility( $path )
{
try {
$acl = $this->getObject( $path )->acl()->get( [ 'entity' => 'allUsers' ] );
return $acl['role'] === Acl::ROLE_READER ?
AdapterInterface::VISIBILITY_PUBLIC :
AdapterInterface::VISIBILITY_PRIVATE;
} catch ( NotFoundException $e ) {
// object may not have an acl entry, so handle that gracefully
return AdapterInterface::VISIBILITY_PRIVATE;
}
}
/**
* Returns a storage object for the given path.
*
* @param string $path
*
* @return \Google\Cloud\Storage\StorageObject
*/
protected function getObject( $path )
{
$path = $this->applyPathPrefix( $path );
return $this->bucket->object( $path );
}
/**
* @param string $visibility
*
* @return string
*/
protected function getPredefinedAclForVisibility( $visibility )
{
return $visibility === AdapterInterface::VISIBILITY_PUBLIC ? 'publicRead' : 'projectPrivate';
}
}
<?php
namespace App\Providers;
use Google\Cloud\Storage\StorageClient;
use Illuminate\Filesystem\FilesystemManager;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Filesystem;
use App\Adapters\GoogleStorageAdapter;
class GoogleCloudStorageServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*/
public function boot()
{
$factory = $this->app->make( 'filesystem' );
/* @var FilesystemManager $factory */
$factory->extend( 'gcs', function ( $app, $config ) {
$storageClient = new StorageClient( [
'projectId' => $config['project_id'],
'keyFilePath' => array_get( $config, 'key_file' ),
] );
$bucket = $storageClient->bucket( $config['bucket'] );
$pathPrefix = array_get( $config, 'path_prefix' );
$storageApiUri = array_get( $config, 'storage_api_uri' );
$adapter = new GoogleStorageAdapter( $storageClient, $bucket, $pathPrefix, $storageApiUri );
return new Filesystem( $adapter );
} );
}
/**
* Register bindings in the container.
*/
public function register()
{
//
}
}
Pada file di atas Anda dapat melihat bahwa StorageClient membutuhkan ProjectId dan keyFilePath yang perlu Anda sediakan, informasi seperti bucket , pathPrefix dan storageApiUri dapat disimpan dalam file .ENV yang akan dibaca oleh filesystems.php yang telah kami buat sebelumnya.
Di dalam .ENV
GOOGLE_CLOUD_KEY_FILE =
GOOGLE_CLOUD_PROJECT_ID =
GOOGLE_CLOUD_STORAGE_BUCKET =
Pada akhirnya Anda hanya perlu memberi tahu aplikasi Anda apa yang telah Anda lakukan dengannya: D
Dalam app.php tambahkan baris berikut:
$ app-> singleton (
Illuminate \ Contracts \ Filesystem \ Factory :: class,
function ($ app) {
return baru Illuminate \ Filesystem \ FilesystemManager ($ app);
});$ app-> configure ('filesystem');
class_alias ('Illuminate \ Support \ Facades \ Storage', 'Storage');$ app-> register (Menerangi \ Filesystem \ FilesystemServiceProvider :: class);
$ app-> register (App \ Providers \ GoogleCloudStorageServiceProvider :: class);
Bagus, Anda sudah selesai sekarang dapat menggunakan layanan GCS.
Cuplikan kode untuk mengunggah file ke GCS
Storage::disk('gcs')->put("Name.pdf", $this->fileContent, 'public');
$pdfUrl = Storage::disk('gcs')->url("Name.pdf");
Sangat tertarik dengan dunia Pemrograman Web & Mobile, saat ini fokus pada bagian Backend Web Developer, menggunakan PHP sebagai bahasa pemrograman utama, biasanya saya menggunakan Laravel.