# 機能設計書 191-ファイルアップロード

## 概要

本ドキュメントは、Chatwootにおける一般的なファイルアップロード機能の設計を記載したものである。この機能により、ユーザーはローカルファイルまたは外部URLからファイルをアップロードし、ActiveStorage Blobとして保存できる。

### 本機能の処理概要

**業務上の目的・背景**：カスタマーサポート業務において、画像やドキュメントなどのファイルを添付する必要が頻繁に発生する。この機能は、エージェントやシステムが必要なファイルをChatwootプラットフォームにアップロードし、会話やメッセージに添付するための基盤を提供する。ファイルを直接アップロードするだけでなく、外部URLからファイルを取得する機能も備えており、柔軟なファイル管理を実現する。

**機能の利用シーン**：エージェントがカスタマーサポート中に画像やPDFなどのファイルを共有する際、また自動化ルールやボットがファイルを送信する際に利用される。キャンペーンメッセージに添付するファイルのアップロードにも使用される。

**主要な処理内容**：
1. ローカルファイルのアップロード（multipart/form-data形式）
2. 外部URLからのファイル取得とアップロード
3. ActiveStorage Blobの作成とストレージへの保存
4. アップロード完了後のファイルURLとBlob IDの返却

**関連システム・外部連携**：ActiveStorageを通じたファイルストレージ（ローカル、Amazon S3、Google Cloud Storage等）との連携。外部URLからのファイル取得ではHTTP/HTTPSプロトコルを使用。

**権限による制御**：アカウントに所属する認証済みユーザーのみがファイルアップロードを実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 11 | 会話詳細画面 | 参照画面 | ファイル添付時のアップロード処理 |

## 機能種別

ファイル操作（アップロード）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| attachment | File | No* | アップロードするファイル（multipart/form-data） | *attachmentまたはexternal_urlのいずれかが必須 |
| external_url | String | No* | ファイル取得元の外部URL | HTTP/HTTPSプロトコルのみ許可 |

### 入力データソース

- 画面からのファイル選択（multipart/form-data形式）
- 外部URLの指定（テキスト入力）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| file_url | String | アップロードされたファイルへのアクセスURL |
| blob_id | String | ActiveStorage Blobの署名付きID |

### 出力先

- JSON形式でAPIレスポンスとして返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ ファイル添付またはURL指定の判定
2. ファイル添付の場合
   └─ 一時ファイルからBlob作成
3. URL指定の場合
   ├─ URLのバリデーション（HTTP/HTTPS確認）
   └─ 外部URLからファイル取得してBlob作成
4. ActiveStorage Blobへの保存
   └─ ファイル名、コンテンツタイプを設定
5. レスポンス返却
   └─ file_urlとblob_idを含むJSONを返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{attachmentあり?}
    B -->|Yes| C[ファイルからBlob作成]
    B -->|No| D{external_urlあり?}
    D -->|Yes| E[URLパース・検証]
    D -->|No| F[エラー: No file or URL provided]
    E --> G{URL形式は正しい?}
    G -->|Yes| H[外部URLからファイル取得]
    G -->|No| I[エラー: Invalid URL provided]
    H --> J{取得成功?}
    J -->|Yes| C
    J -->|No| K[エラー: Failed to fetch file]
    C --> L[ActiveStorage Blob作成・保存]
    L --> M[file_urlとblob_idを返却]
    F --> N[エラーレスポンス]
    I --> N
    K --> N
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-191-01 | 入力必須チェック | attachmentまたはexternal_urlのいずれかが必須 | 常時 |
| BR-191-02 | URL形式制限 | external_urlはHTTPまたはHTTPSプロトコルのみ許可 | URL指定時 |

### 計算ロジック

なし

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ファイルアップロード | active_storage_blobs | INSERT | Blobメタデータの登録 |
| ファイルアップロード | active_storage_attachments | INSERT | 必要に応じて添付関連付け |

### テーブル別操作詳細

#### active_storage_blobs

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | filename | アップロードファイル名 | - |
| INSERT | content_type | ファイルのMIMEタイプ | - |
| INSERT | byte_size | ファイルサイズ | - |
| INSERT | checksum | ファイルのMD5チェックサム | - |
| INSERT | key | ストレージ上のキー | 自動生成 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 422 | Unprocessable Entity | attachmentもexternal_urlも指定されていない | エラーメッセージ「No file or URL provided」を返却 |
| 422 | Unprocessable Entity | URLの形式が不正（HTTP/HTTPS以外） | エラーメッセージ「Invalid URL provided」を返却 |
| 422 | Unprocessable Entity | 外部URLからのファイル取得失敗 | エラーメッセージ「Failed to fetch file from URL」を返却 |
| 500 | Internal Server Error | 予期しないエラー | エラーメッセージ「An unexpected error occurred」を返却 |

### リトライ仕様

- 外部URLからのファイル取得失敗時はリトライなし（即座にエラー返却）

## トランザクション仕様

- ActiveStorage Blobの作成は単一トランザクションで実行
- ファイル取得とBlob作成は同一トランザクション内

## パフォーマンス要件

- 外部URLからのファイル取得にはタイムアウトが適用される（OpenURI標準）

## セキュリティ考慮事項

- 認証済みユーザーのみアクセス可能
- 外部URLはHTTP/HTTPSプロトコルのみ許可（プロトコル検証）
- blob_idは署名付きIDを使用し、不正アクセスを防止

## 備考

- このAPIはアカウントスコープで動作し、アカウントに所属するユーザーのみが利用可能
- 大容量ファイルのアップロードにはダイレクトアップロード機能（No.192）の利用を推奨

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | upload_controller.rb | `app/controllers/api/v1/accounts/upload_controller.rb` | ファイルアップロードの処理フロー全体を把握 |

**主要処理フロー**:
1. **2-11行目**: `create`アクション - attachmentまたはexternal_urlの判定と処理分岐
2. **16-18行目**: `create_from_file` - ローカルファイルからのBlob作成
3. **20-26行目**: `create_from_url` - URLからのファイル取得処理
4. **28-39行目**: `parse_uri`と`validate_uri` - URL検証ロジック
5. **41-51行目**: `fetch_and_process_file_from_uri` - 外部ファイル取得とエラーハンドリング
6. **53-58行目**: `create_and_save_blob` - ActiveStorage Blob作成の核心部分

**読解のコツ**: Ruby on Railsの`ActiveStorage::Blob.create_and_upload!`メソッドがファイルの保存処理を担当している。このメソッドはファイルをストレージサービス（設定による）にアップロードし、メタデータをDBに保存する。

#### Step 2: 親コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | base_controller.rb | `app/controllers/api/v1/accounts/base_controller.rb` | アカウントスコープの認証・認可処理 |

**主要処理フロー**:
- **4行目**: `before_action :current_account` - 現在のアカウント設定

### プログラム呼び出し階層図

```
Api::V1::Accounts::UploadController#create
    │
    ├─ create_from_file (attachmentがある場合)
    │      └─ create_and_save_blob
    │             └─ ActiveStorage::Blob.create_and_upload!
    │
    └─ create_from_url (external_urlがある場合)
           ├─ parse_uri
           │      └─ validate_uri
           └─ fetch_and_process_file_from_uri
                  └─ create_and_save_blob
                         └─ ActiveStorage::Blob.create_and_upload!
```

### データフロー図

```
[入力]                    [処理]                              [出力]

attachment (File)    ───▶ UploadController#create_from_file
                              │
                              ▼
                         create_and_save_blob
                              │
                              ▼
                         ActiveStorage::Blob ───▶ { file_url, blob_id }

external_url (String) ───▶ UploadController#create_from_url
                              │
                              ▼
                         parse_uri / validate_uri
                              │
                              ▼
                         fetch_and_process_file_from_uri
                              │
                              ▼
                         create_and_save_blob
                              │
                              ▼
                         ActiveStorage::Blob ───▶ { file_url, blob_id }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| upload_controller.rb | `app/controllers/api/v1/accounts/upload_controller.rb` | ソース | ファイルアップロードのコントローラー |
| base_controller.rb | `app/controllers/api/v1/accounts/base_controller.rb` | ソース | アカウントスコープの基底コントローラー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（355行目） |
