Cloud Run→Cloud Storageの画像保存


メモはたくさんあるのですが、まとめる時間がないです。

とどいた案件

「Google Cloud(以下GCP)でWebアプリ走らせて」

お、おう、、、

このタイミングで

いずれAWSかGCPに取り組まなきゃと思ってましたが、まさかのこのタイミングで、、

環境

PHP7 Laravel8.x Dockerつかってます

Cloud Runここが困ったぞ

コストカットのために未使用時はサーバがすぐに止まる設定にしているのですが、アップロードした写真などはアクセス終了後に消える仕様らしい。

なので、デプロイ後にアプリからアップロードしたプロフィール写真や、発行したPDFなどはサーバがお眠りになると消えるらしい。

で、いろいろググると、S3か、FTP(SFTP)がオススメらしいと。

S3は別のバックアップで使っているのですが、お客様にまたS3を契約してもらうのは億劫なので、Google Cloud Storageを利用することにしました。

Cloud RunからCloud Storageにどうやってアップするの?

よくわかない

いろいろ検索した結果、、、よくわからない。

非エンジニア+個人開発の限界です。

これが使えた

別プロジェクトの方にお尋ねして、教えていただいた記事からリポジトリをたどって、以下にたどりつきました。

https://github.com/Superbalist/laravel-google-cloud-storage

ちょっと古いけれど、Laravel8.xコンパチと書いてる。

ほかにもいくつかあるのですが、PHP8が必須でこちらの環境(php7)には適合せず。

インストール

キーのJSONが取得済みであることが前提です。

アプリ側のコンソールで、Laravelのsrc内に入り

composer require superbalist/laravel-google-cloud-storage

初期設定

laravelApp/src/laravelapp/config/filesystems.phpに以下を追加します。

config/filesystems.php
'gcs' => [
    'driver' => 'gcs',
    'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'GCPのプロジェクトID'),
    'key_file' => env('GOOGLE_CLOUD_KEY_FILE', null), //キーのJSONファイルへのパス
    'bucket' => env('GOOGLE_CLOUD_STORAGE_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 エラーでたっぽいんで使っていません
],

bladeに追加

つぎにフォームの設定です。該当のbladeに以下を追加しました。

post.blade.php
<form action="{{route('save')}}" method="post" enctype="multipart/form-data">
    @csrf

    <!-- 画像保存 -->
    <div class="pt-2">
    <input id="image_path" type="file" name="image_path" >
    </div>
  
    <div class="pt-2">
    <input class="btn btn-info p-2" type="submit" value="作成">
    <a type="button" class="btn btn-success p-2" href="/nanika_view">キャンセル</a>
   </div>

saveが来るとControllerに飛ばすようweb.phpに設定済みです。

Controllerに追加

Controllerに以下を追加しました

ImageController.php
public function save(Request $request)
    {
        // バリデートは省略
        

    $input_content = new Image_lists();
    $input_content->image_name = $request['image_name'];

    // 画像ファイルの保存場所指定
    if(request('image_path')){
        $filename=$request->image_path->getClientOriginalName();//今回は元のファイル名を使用

        //Cloud Strageを定義
       // $disk = Storage::disk('gcs');

        // ファイル名を指定して保存の場合、3つめのgcsをつけないとローカル保存(=時間がたつと消える)になる
        $url = request('image_path')->storeAs('保存フォルダまでのパス', $filename, 'gcs');
        //↑ハッシュ保存の場合はputでOK

        // データベースに保存するファイルパス用 
        $path = 'https://storage.googleapis.com/(バケット、保存フォルダまでのURL)';
        $path .= $filename; // $urlの意味が無い、、

		//DB保存用に絶対パスを保存内容に入れる
        $input_content->image_path = $path;
    }
	//DB保存
    $input_content->save();
 
    // 保存後にimagelist viewの画面へリダイレクト
    return redirect(route('imagelist'));
    }

おつかれさまでした。