はじめに
この記事ではLaravelでファイルアップロードしたファイルをGCSで管理した時の備忘録です
やり方
事前準備:GCPのプロジェクト・バケットの作成
以下の記事を参考にしました🙇♂️
作成したStorage
に以下の権限を付与しておく
.env
に登録したバケット名を入力する
.env
GCS_BUCKET_NAME="hoge-bucket"
.env
の値をapp.php
から参照する
src/laravel/config/app.php
'gcp_bucket_name' => env('GCS_BUCKET_NAME', 'hoge-bucket'),
GCSを操作するパッケージをインストール
composer require google/cloud-storage
google/cloud-storageをインスタンス化する
- 事前準備で作成したバケットの認証キーを
storage
直下のディレクトリに移動します
Config('app.gcp_bucket_name');
:app.php
からバケット名を参照します
$url = file_get_contents()
:事前準備で作成したキーファイルを参照します
new StorageClient([バケット名,サービスアカウントのキーファイル])
:
$client->bucket();
:バケットを生成します
src/laravel/app/Services/Utilities/UtilityService.php
class UtilityService
{
public $bucket;
public $bucketOptions;
public function __construct()
{
$projectId = Config('app.gcp_bucket_name');
$url = file_get_contents(storage_path('app/local-service-account.json', true));
$client = new StorageClient([
'projectId' => $projectId,
'keyFile' => json_decode($url, true)
]);
$this->bucket = $client->bucket($projectId);
$this->bucketOptions = [
'resumable' => true, // アップロードを再開可能に行うか
'name' => '',
'metadata' => [
// 日本語化
'contentLanguage' => 'ja'
]
];
}
/**
* 仮登録GCS保存名を作成
*
* @param UploadedFile $file
* @param string $dirName
* @param string $uniqueKey
* @param array $options
* @return array
*/
public function setBucketOptions(UploadedFile $file, string $dirName, string $uniqueKey, array $options): array {
$extension = $file->extension();
$fileName = "{$uniqueKey}_{$dirName}.{$extension}";
// 保存ディレクトリ生成
$options['name'] = "tmp/images/{$uniqueKey}/{$dirName}/{$fileName}";
return $options;
}
}
送信時にGCSに一時保存する
tmp/images/一意な値
に保存するようにします
src/laravel/app/Services/SkillSheet/SkillSheetService.php
protected UtilityService $utilityService;
public function __construct()
{
$this->utilityService = new UtilityService();
}
/**
* GCSへの仮保存
*
* @param StoreSkillSheetRequest $request
* @param string $uniqueKey
* @return array
*/
public function tmpStorageToGcsBucket(StoreSkillSheetRequest $request, string $uniqueKey): array
{
// バケットを生成
$bucket = $this->utilityService->bucket;
// 登録した保存名を保持していく
$saveNames = [];
// 写真・動画・その他画像を1件ずつ振り分けする
foreach ($request->file() as $key => $files) {
foreach ($files as $file) {
$options = $this->utilityService->setBucketOptions(
$file,
$key,
$uniqueKey,
$this->utilityService->bucketOptions
);
$saveNames[$key] = $options['name'];
$bucket->upload(
fopen($file, 'rb'),
$options
);
}
}
return $saveNames;
}
GCSに一時保存した画像を正式に保存する場所に移動します
images/一意な値・ユーザーID
に保存するようにします
セッションに一時保存したファイル名を保持している状態と仮定します
/**
* GCS保存
*
* @param integer $id
* @param SkillSheet $target
* @param array $updSkillSheet
* @return array
*/
public
function storageToGcsBucket(int $id, SkillSheet $target, array $updSkillSheet): array
{
// セッションを破棄する
$saveNames = Session('saveNames');
session()->forget('saveNames');
// バケットイニシャライズ
$bucket = $this->utilityService->bucket;
// 仮登録したデータをコピーして移動させてから削除する
foreach ($saveNames as $key => $v) {
// 仮登録したオブジェクトがバケットに存在する場合は移管する
$targetObject = $bucket->object($v);
$extension = pathinfo($v)['extension'];
$name = "skill_sheet/{$id}/{$key}/{$id}_{$key}.{$extension}";
// オブジェクトが存在する場合は仮置きからコピーして移動する・仮置きは削除する
if ($targetObject->exists()) {
$targetObject->copy($bucket, ['name' => $name]);
$targetObject->delete();
}
// 登録データが既にある場合は差し替える(更新)
if ($target->pr_image_path) {
// 差し替え前のオブジェクトを取得
$beforeObject = $bucket->object($target->pr_image_path);
// 差し替え前のオブジェクトがあれば削除
if ($beforeObject->exists()) {
$beforeObject->delete();
} else {
// 差し替え前のオブジェクトがないのにDBに登録されている場合はリセットする
$updSkillSheet['pr_image_path'] = null;
}
}
$updSkillSheet['pr_image_path'] = $name;
}
return $updSkillSheet;
}