Google Cloud Storage アップロード

概要

Google Cloud Storage (GCS) アップロード機能は、Google Cloud Storageにファイルをアップロード、ダウンロード、管理するための安全で効率的な方法を提供します。この機能は署名付きURLを使用して、クライアントからGCSへの直接アップロードを可能にし、ファイル転送のためのアプリケーションサーバーをバイパスすることでパフォーマンスを向上させます。また、GCSに保存されているファイルのリスト表示、削除、一時的なアクセスURLの取得などのメソッドも提供します。

スワッガーリンク

APIドキュメント: Gcs Upload

アクティビティ図

---
config:
  theme: base
  layout: dagre
  flowchart:
    curve: linear
    htmlLabels: true
  themeVariables:
    edgeLabelBackground: "transparent"
---
flowchart TD
    Client[クライアントアプリケーション]
    API[UploadGcsController]
    GCSService[GcsService]
    ImportService[ImportReviewService]
    GCS[(Google Cloud Storage)]
    
    Client --- Step1[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>1</span>
            <p style='margin-top: 8px'>署名付きURLを要求</p>
        </div>
    ]
    Step1 --> API

    API --- Step2[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>2</span>
            <p style='margin-top: 8px'>署名付きURLを生成</p>
        </div>
    ]
    Step2 --> ImportService

    ImportService --- Step3[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>3</span>
            <p style='margin-top: 8px'>GCSからURLを要求</p>
        </div>
    ]
    Step3 --> GCSService

    GCSService --- Step4[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4</span>
            <p style='margin-top: 8px'>署名付きURLを返す</p>
        </div>
    ]
    Step4 --> GCS

    GCS --- Step5[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5</span>
            <p style='margin-top: 8px'>クライアントにURLを返す</p>
        </div>
    ]
    Step5 --> GCSService
    GCSService --> ImportService
    ImportService --> API
    API --> Client

    Client --- Step6[
        <div style='text-align: center'>
            <span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6</span>
            <p style='margin-top: 8px'>ファイルを直接アップロード</p>
        </div>
    ]
    Step6 --> GCS
    
    style Client fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style API fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
    style GCSService fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style ImportService fill:#f0f8e6,stroke:#339933,stroke-width:2px
    style GCS fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
    style Step1 fill:transparent,stroke:transparent,stroke-width:1px
    style Step2 fill:transparent,stroke:transparent,stroke-width:1px
    style Step3 fill:transparent,stroke:transparent,stroke-width:1px
    style Step4 fill:transparent,stroke:transparent,stroke-width:1px
    style Step5 fill:transparent,stroke:transparent,stroke-width:1px
    style Step6 fill:transparent,stroke:transparent,stroke-width:1px

ケースドキュメント

ケース1: 直接アップロード用の署名付きURLを生成

説明

クライアントがGoogle Cloud Storageにファイルを直接アップロードするための署名付きURLを要求します。

シーケンス図

sequenceDiagram
    participant Client as クライアント
    participant API as UploadGcsController
    participant Service as ImportReviewService
    participant GCSService as GcsService
    participant GCS as Google Cloud Storage
    
    Note over Client,GCS: 署名付きURL生成フロー
    
    rect rgb(200, 255, 200)
    Note right of Client: 正常系フロー
    
    Client->>API: GET /api/v1/general/upload-file/gcs/get-signed-url
    
    rect rgb(200, 230, 255)
    Note right of API: 入力検証
    API->>API: filenameパラメータを検証
    end
    
    rect rgb(200, 255, 255)
    Note right of API: ビジネスロジック
    API->>Service: getSignedUrl(filename)
    Service->>Service: グループと日付構造でパスを生成
    Service->>GCSService: getSignedUrl(path, contentType, expiration)
    GCSService->>GCS: PUTメソッドで署名付きURLを生成
    GCS-->>GCSService: 署名付きURLを返す
    GCSService-->>Service: URLデータ、パス、有効期限を返す
    Service-->>API: URLデータを返す
    end
    
    API-->>Client: 200 OK (署名付きURLとメタデータ)
    end
    
    rect rgb(255, 200, 200)
    Note right of Client: エラーハンドリング
    rect rgb(255, 230, 230)
    alt バリデーションエラー
        API-->>Client: 422 バリデーションエラー
    else GCSエラー
        GCS-->>GCSService: エラーレスポンス
        GCSService-->>Service: エラー結果
        Service-->>API: エラー結果
        API-->>Client: 400 Bad Request
    end
    end
    end

ステップ

ステップ 1: 署名付きURLのリクエスト

  • 説明: クライアントがファイルアップロード用の署名付きURLをリクエスト
  • リクエスト: GET /api/v1/general/upload-file/gcs/get-signed-url
  • パラメータ:
    • filename: アップロードするファイル名(必須)
  • バリデーション:
    • ファイル名は文字列で255文字以下である必要があります

ステップ 2: 署名付きURLの生成

  • 説明: システムが直接アップロード用の署名付きURLを生成
  • アクション:
    • パス構造を生成: temp/{group_id}/{date}/{filename}
    • コンテンツタイプを'text/csv'に設定
    • PUTメソッドでGoogle Cloud Storageから署名付きURLを要求
    • URLを15分(900秒)で期限切れに設定

ステップ 3: クライアントにURLを返す

  • 説明: 署名付きURLとメタデータをクライアントに返す
  • レスポンス:
    • 成功: 200 OK(成功フラグ、URL、パス、有効期限、コンテンツタイプを含む署名付きURLデータ)
    • エラー: 400 Bad Request(エラーメッセージ)

エラーハンドリング

  • ログ記録
    • URL生成失敗はアプリケーションログに記録されます
  • エラー詳細:
    ステータスコード エラーメッセージ 説明
    422 バリデーション失敗 filenameパラメータが無効な場合
    400 署名付きURLの生成に失敗 GCSがエラーを返すかサービスが失敗した場合

ケース2: サーバー経由でのファイルアップロード

説明

クライアントがサーバーにファイルをアップロードし、サーバーがGoogle Cloud Storageにアップロードします。

シーケンス図

sequenceDiagram
    participant Client as クライアント
    participant API as UploadGcsController
    participant Service as GcsService
    participant GCS as Google Cloud Storage
    
    Note over Client,GCS: サーバーサイドアップロードフロー
    
    rect rgb(200, 255, 200)
    Note right of Client: 正常系フロー
    
    Client->>API: POST /api/v1/general/upload-file/gcs/upload-file
    
    rect rgb(200, 230, 255)
    Note right of API: 入力検証
    API->>API: ファイルとパスを検証
    end
    
    rect rgb(200, 255, 255)
    Note right of API: ビジネスロジック
    API->>Service: uploadFile(file, path)
    Service->>Service: ユニークなファイル名を生成
    Service->>GCS: ファイルをアップロード
    GCS-->>Service: アップロード確認
    Service-->>API: ファイルパスとURLを返す
    end
    
    API-->>Client: 200 OK (ファイルパスとURL)
    end
    
    rect rgb(255, 200, 200)
    Note right of Client: エラーハンドリング
    rect rgb(255, 230, 230)
    alt バリデーションエラー
        API-->>Client: 422 バリデーションエラー
    else アップロードエラー
        GCS-->>Service: エラーレスポンス
        Service-->>API: エラー結果
        API-->>Client: 500 内部サーバーエラー
    end
    end
    end

ステップ

ステップ 1: ファイルアップロードリクエスト

  • 説明: クライアントがサーバーにファイルをアップロード
  • リクエスト: POST /api/v1/general/upload-file/gcs/upload-file
  • パラメータ:
    • file: アップロードするファイル(必須)
    • path: ファイルが保存されるパス(必須)
  • バリデーション:
    • ファイルが存在し、10MB以下である必要があります
    • パスは文字列である必要があります

ステップ 2: アップロード処理

  • 説明: システムがファイルをGCSにアップロード
  • アクション:
    • ランダム文字列を追加してパスの一意性を確保
    • ファイルのMIMEタイプに基づいて適切なコンテンツタイプを設定
    • ファイルをGCSにアップロード

ステップ 3: 結果を返す

  • 説明: アップロード結果をクライアントに返す
  • レスポンス:
    • 成功: 200 OK(ファイルパスとパブリックURL)
    • エラー: 適切なエラーコードとメッセージ

エラーハンドリング

  • ログ記録
    • アップロード失敗はアプリケーションログに記録されます
  • エラー詳細:
    ステータスコード エラーメッセージ 説明
    422 バリデーション失敗 ファイルまたはパスパラメータが無効な場合
    500 ファイルのアップロードに失敗: {error} GCSがエラーを返す場合

ケース3: ディレクトリ内のファイル一覧

説明

クライアントがGoogle Cloud Storageの特定のディレクトリ内のファイル一覧を要求します。

シーケンス図

sequenceDiagram
    participant Client as クライアント
    participant API as UploadGcsController
    participant Service as GcsService
    participant GCS as Google Cloud Storage
    
    Note over Client,GCS: ファイル一覧フロー
    
    rect rgb(200, 255, 200)
    Note right of Client: 正常系フロー
    
    Client->>API: GET /api/v1/general/upload-file/gcs/list-files
    
    rect rgb(200, 230, 255)
    Note right of API: 入力検証
    API->>API: ディレクトリと再帰フラグを検証
    end
    
    rect rgb(200, 255, 255)
    Note right of API: ビジネスロジック
    API->>Service: listFiles(directory, recursive)
    Service->>GCS: ディレクトリ内のファイルを一覧表示
    GCS-->>Service: ファイルリストを返す
    Service-->>API: ファイルリストとディレクトリを返す
    end
    
    API-->>Client: 200 OK (ファイルリスト)
    end
    
    rect rgb(255, 200, 200)
    Note right of Client: エラーハンドリング
    rect rgb(255, 230, 230)
    alt バリデーションエラー
        API-->>Client: 422 バリデーションエラー
    else GCSエラー
        GCS-->>Service: エラーレスポンス
        Service-->>API: エラー結果
        API-->>Client: 500 内部サーバーエラー
    end
    end
    end

ステップ

ステップ 1: ファイルリストのリクエスト

  • 説明: クライアントがディレクトリ内のファイルリストをリクエスト
  • リクエスト: GET /api/v1/general/upload-file/gcs/list-files
  • パラメータ:
    • directory: ファイルを一覧表示するディレクトリ(オプション、デフォルト: ルート)
    • recursive: ファイルを再帰的に一覧表示するかどうか(オプション、デフォルト: false)
  • バリデーション:
    • ディレクトリは文字列である必要があります
    • 再帰フラグはブール値である必要があります

ステップ 2: ファイルリストの取得

  • 説明: システムがGCSからファイルリストを取得
  • アクション:
    • 指定されたディレクトリのファイルをGCSにクエリ
    • ファイルメタデータ(サイズ、最終更新日など)を含める
    • フォーマットされたファイルリストを返す

ステップ 3: ファイルリストを返す

  • 説明: ファイルリストをクライアントに返す
  • レスポンス:
    • 成功: 200 OK(ファイルリストとディレクトリ情報)
    • エラー: 適切なエラーコードとメッセージ

エラーハンドリング

  • ログ記録
    • ファイル一覧表示失敗はアプリケーションログに記録されます
  • エラー詳細:
    ステータスコード エラーメッセージ 説明
    422 バリデーション失敗 ディレクトリまたは再帰パラメータが無効な場合
    500 ファイルの一覧表示に失敗: {error} GCSがエラーを返す場合

データベース関連テーブルとフィールド

erDiagram
    review_upload_histories {
        bigint id PK
        bigint user_id FK "usersテーブルへの参照"
        bigint group_id FK "groupsテーブルへの参照"
        string file_name "アップロードされたファイル名"
        string gcs_path "ファイルが保存されているGoogle Cloud Storageのパス"
        tinyInteger status "アップロードステータス: 0=未処理, 1=処理中, 2=成功, 3=失敗"
        string error_reason "アップロード失敗時のエラーメッセージ(null可)"
        timestamp validated_at "ファイルが検証された時刻(null可)"
        timestamp created_at
        timestamp updated_at
    }
    users {
        bigint id PK
        string name "ユーザーのフルネーム"
        string email "ユーザーのメールアドレス"
    }
    groups {
        bigint id PK
        string name "グループ名"
    }

    review_upload_histories ||--o{ users : 所属
    review_upload_histories ||--o{ groups : 所属

主要機能

  • 直接アップロードサポート: クライアントからGCSへの直接アップロード用の署名付きURLを生成
  • グループベースのパス構造: ユーザーのグループと日付に基づく自動パス生成
  • CSVファイルサポート: 適切なコンテンツタイプ処理によるCSVファイルアップロードの最適化
  • エラーハンドリング: 詳細なログ記録による包括的なエラーハンドリング
  • セキュリティ: 設定可能な有効期限を持つ署名付きURL
  • ファイル管理: ファイル一覧表示と管理操作のサポート

セキュリティ考慮事項

  • グループ分離: ファイルはグループ固有のディレクトリに保存されます
  • 署名付きURLの有効期限: 生成されたURLは15分で期限切れになります
  • 入力検証: すべてのエンドポイントに包括的な入力検証が含まれています
  • エラーログ記録: 失敗した操作は監視とデバッグのためにログに記録されます