【Laravel】Storageを利用せずに、SDKを利用してGCSに画像をアップロードする
この記事について
Laravel の FileSystem を利用して GCS に画像をアップロードする ことは割と往々にしてあると思います。
AWSのS3を利用する場合は、デフォルトでStorage::disk('s3')として利用できるのですが、GCSの場合は、デフォルトでは利用できません。
今回は、SDKを利用して、GCSに画像をアップロードする方法を紹介します。
対象読者
- Storageを経由せずに、SDKを利用してGCSに画像をアップロードする方法を知りたい方
SDKを利用してGCSに画像をアップロードする
SDKをインストールする
まずは、SDKをインストールします。
$ composer require google/cloud-storage
GCSの認証情報を取得する
GCSの認証情報を取得します。
今回は、JSON形式で取得します。
バージョン管理はしないので、.gitignoreに追加しておきます。
$ echo "storage/app/google-cloud-storage.json" >> .gitignore
GCSを操作するクラスを作成する
毎回、認証情報を読み込んで、GCSのクライアントを作成するのは面倒なので、クラスを作成して、インスタンス化して利用します。
まずは、コードの全体像を見てみましょう。
<?php
namespace App\utilities;
use DateTime;
use Google\Cloud\Storage\Bucket;
use Google\Cloud\Storage\StorageClient;
class GcsProviderService
{
private Bucket $gcsBucket;
public function __construct()
{
$projectID = config('app.gcp_bucket_name', 'hoge');
$keyPath = file_get_contents(storage_path('app/google-cloud-storage.json', true));
$storage = new StorageClient([
'projectId' => $projectID,
'keyFile' => json_decode($keyPath, true),
]);
$this->gcsBucket = $storage->bucket($projectID);
}
public function getGcsBucket(): Bucket
{
return $this->gcsBucket;
}
public function getSignedUrl($filePath)
{
$bucket = $this->getGcsBucket();
$object = $bucket->object($filePath);
$expiration = new DateTime('+24 hour');
if(!$object->exists()){
return null;
}
return $object->signedUrl($expiration);
}
public function uploadFile($file, $prefix)
{
if (!$file->isValid()) {
return null;
}
$fileContents = file_get_contents($file);
$bucket = $this->getGcsBucket();
$object = $bucket->upload(
$fileContents,
[
'name' => $prefix . '/' . $file->getClientOriginalName()
]
);
if ($object && $object->info()['selfLink']) {
return $object->info()['selfLink'];
}
return null;
}
}
コードの説明
GCSは、バケットという単位でファイルを管理します。
StorageClientを利用することで、GCSにアクセスすることができます。
毎回、StorageClientをインスタンス化するのは面倒なので、コンストラクタでインスタンス化して、プロパティに保持しておきます。
<?php
$storage = new StorageClient([
'projectId' => $projectID,
'keyFile' => json_decode($keyPath, true),
]);
file_get_contents($file)
でBufferを取得して、$bucket->upload
でアップロードします。
この手順を踏むことで、GCSに画像をアップロードすることができます。
Bufferを取得せずにファイル情報をそのままアップロードしても成功はしますが、画像の実体がGCSにアップロードされないので、注意が必要です。
$fileContents = file_get_contents($file);
サインURLを取得する
GCSにアップロードした画像を、ブラウザから参照する場合は、サインURLを取得する必要があります。
サインURLを取得するには、$object->signedUrl($expiration)
を利用します。
有効期限を指定する必要がありますので、DateTime
を利用します。
exists
で、ファイルが存在するかを確認してから、サインURLを取得しするようにすることで万が一、ファイルが存在しない場合にエラーを回避することができます。
<?php
public function getSignedUrl($filePath)
{
$bucket = $this->getGcsBucket();
$object = $bucket->object($filePath);
$expiration = new DateTime('+24 hour');
if(!$object->exists()){
return null;
}
return $object->signedUrl($expiration);
}
最後に
GCSに画像をアップロードする方法を紹介しました。
Storageを利用する場合と比べると、少し面倒ですが、SDKを利用することで、柔軟にGCSを利用することができます。
S3を利用する場合は Storage::disk('s3')
で利用できるので、SDKを利用する必要は基本的にないと思います。
必要に応じて、SDKを利用して、GCSを利用してみてください。
また、認証情報をバージョン管理しないように、.gitignoreに追加することを忘れないようにしてください。
Discussion