# 帳票設計書 4-FilesystemAdapter response

## 概要

本ドキュメントは、Laravel FrameworkにおけるFilesystemAdapter::response()（ストレージレスポンス）機能の設計仕様を定義する。ストレージに保存されたファイルをレスポンスとして出力する機能であり、Storage::response()で利用可能。

### 本帳票の処理概要

FilesystemAdapter::response()は、Laravelのファイルストレージ（Storage Facade）に保存されたファイルをHTTPレスポンスとして直接クライアントに送信する機能を提供する。ローカルディスク、S3、その他のクラウドストレージからファイルを取得し、ストリーミング形式で出力する。

**業務上の目的・背景**：アプリケーションでは、アップロードされたファイルや生成されたレポートをストレージに保存し、ユーザーの要求に応じて配信する必要がある。response()メソッドを使用することで、ストレージの抽象化レイヤーを通じて、異なるストレージドライバー（ローカル、S3、FTP等）から一貫した方法でファイルをレスポンスとして返却できる。

**帳票の利用シーン**：
- アップロードされた画像ファイルのインライン表示
- ストレージに保存されたPDFの直接表示
- S3等のクラウドストレージからのファイル配信
- プライベートストレージ内ファイルの認証付き配信

**主要な出力内容**：
1. ストレージからのファイルストリーミングレスポンス
2. 自動検出されたMIMEタイプヘッダー
3. ファイルサイズ情報（Content-Length）
4. Content-Dispositionヘッダー（インライン表示デフォルト）

**帳票の出力タイミング**：Storage::response()メソッドの呼び出し時にStreamedResponseが生成され、ストレージからのファイルストリーミングが開始される。

**帳票の利用者**：アプリケーション開発者、ファイル管理システムのエンドユーザー

## 帳票種別

ストレージファイルレスポンス / インライン表示

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| - | 任意の画面 | 開発者定義 | Storage::response()呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | ストレージ内ファイル形式に依存 |
| 用紙サイズ | - |
| 向き | - |
| ファイル名 | $nameパラメータまたはファイル名から取得 |
| 出力方法 | HTTPストリーミングレスポンス（インライン表示デフォルト） |
| 文字コード | ファイル依存 |

### response()固有設定

| 項目 | 内容 |
|-----|------|
| Content-Type | mimeType()で自動検出 |
| Content-Length | size()で自動取得 |
| Content-Disposition | inline（デフォルト）または指定値 |
| serveCallback | カスタムサーバーコールバック対応 |

## 帳票レイアウト

### レイアウト概要

FilesystemAdapter::response()はストレージ内ファイルをストリーミング出力するため、レイアウト構造はファイル自体に依存する。

```
┌─────────────────────────────────────┐
│          HTTPヘッダー部              │
├─────────────────────────────────────┤
│          ファイルコンテンツ           │
│       （ストリーミング出力）          │
│                                     │
└─────────────────────────────────────┘
```

### ヘッダー部

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | Content-Type | ファイルのMIMEタイプ | $this->mimeType($path) | image/png等 |
| 2 | Content-Length | ファイルサイズ | $this->size($path) | バイト数 |
| 3 | Content-Disposition | 表示モード | $dispositionパラメータ | inline; filename="xxx" |

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | ファイルコンテンツ | ストレージ内ファイル | readStream($path) | バイナリ | - |

### フッター部

フッター部は特に定義されない。

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| path | ストレージ内のファイルパス | Yes |
| name | 表示用ファイル名 | No（デフォルト: basename($path)） |
| headers | 追加HTTPヘッダー | No |
| disposition | inline / attachment | No（デフォルト: inline） |

### ソート順

ファイル出力のため、ソート順は適用されない。

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| - | - | - |

### 改ページ条件

ファイル出力のため、改ページ条件は適用されない。

## データベース参照仕様

### 参照テーブル一覧

FilesystemAdapter::response()自体はデータベースを参照しない。ファイルパスの取得にデータベースを参照する場合は、呼び出し元で処理する。

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| - | - | - |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| fallbackName | str_replace('%', '', Str::ascii($name)) | - | 非ASCII文字のフォールバック |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[response()メソッド呼び出し] --> B[StreamedResponse生成]
    B --> C[Content-Type設定]
    C --> D[Content-Length設定]
    D --> E{Content-Disposition設定済み?}
    E -->|No| F[fallbackName生成]
    F --> G[Content-Disposition設定]
    E -->|Yes| H[ヘッダー設定スキップ]
    G --> I[setCallback設定]
    H --> I
    I --> J[readStream実行]
    J --> K[fpassthru出力]
    K --> L[fclose]
    L --> M[レスポンス完了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| ファイル不存在 | ストレージにファイルがない | UnableToReadFile | ファイルパスを確認 |
| 読み取りエラー | ストリーム取得失敗 | UnableToReadFile | ストレージ設定確認 |
| MIMEタイプ取得失敗 | ファイル形式判定不可 | UnableToRetrieveMetadata | ヘッダーを手動設定 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 単一ファイル |
| 目標出力時間 | ファイルサイズ・帯域に依存 |
| 同時出力数上限 | サーバーリソースに依存 |

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

- プライベートストレージへのアクセスは認証・認可を適切に実装すること
- パス指定にユーザー入力を使用する場合は、パストラバーサル対策が必要
- S3等の署名付きURLを使用する場合は、有効期限を適切に設定すること
- Content-Dispositionのファイル名にはサニタイズが必要

## 備考

- Symfony\Component\HttpFoundation\StreamedResponseを使用している
- serveUsing()メソッドでカスタムサーバーコールバックを定義可能
- serve()メソッドはリクエスト情報を受け取ってresponse()を呼び出す

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

FilesystemAdapterはFlysystemをラップしており、ストレージ操作の抽象化レイヤーを提供している。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | クラス全体の構造を理解する |
| 1-2 | FilesystemContract.php | `src/Illuminate/Contracts/Filesystem/Filesystem.php` | インターフェース定義を確認 |

**読解のコツ**: FilesystemAdapterはLeague\Flysystem\FilesystemOperatorをラップしており、様々なストレージドライバーを抽象化している。

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

処理の起点となるresponse()メソッドを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | response()メソッドの実装を確認 |

**主要処理フロー**:
1. **行318-353**: response()メソッドの実装
2. **行329**: StreamedResponseインスタンス生成
3. **行331-332**: Content-TypeとContent-Length設定（??=演算子使用）
4. **行334-341**: Content-Disposition設定
5. **行346-350**: setCallback()でreadStream/fpassthru/fclose設定

#### Step 3: 関連メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | fallbackName()メソッド |
| 3-2 | FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | serve()メソッド |
| 3-3 | FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | readStream()メソッド |

**主要処理フロー**:
- **行384-393**: fallbackName()メソッド - 非ASCII文字をASCIIにフォールバック
- **行355-369**: serve()メソッド - カスタムコールバック対応
- **行694-703**: readStream()メソッド - ストリーム取得

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

```
FilesystemAdapter::response()
    │
    ├─ new StreamedResponse()
    │
    ├─ $this->mimeType($path)
    │      └─ $this->driver->mimeType($path)
    │
    ├─ $this->size($path)
    │      └─ $this->driver->fileSize($path)
    │
    ├─ fallbackName($filename)
    │      └─ Str::ascii($name)
    │
    ├─ headers->makeDisposition()
    │
    └─ setCallback()
           ├─ $this->readStream($path)
           ├─ fpassthru($stream)
           └─ fclose($stream)
```

### データフロー図

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

ストレージパス  ───▶ FilesystemAdapter    ───▶ HTTPレスポンス
$path                 ::response()             (StreamedResponse)
                          │
                          ▼
                    Flysystem Driver
                          │
                          ▼
                    readStream()
                          │
                          ▼
                    fpassthru()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FilesystemAdapter.php | `src/Illuminate/Filesystem/FilesystemAdapter.php` | ソース | response()メソッドの実装 |
| Filesystem.php | `src/Illuminate/Contracts/Filesystem/Filesystem.php` | ソース | インターフェース定義 |
| Storage.php | `src/Illuminate/Support/Facades/Storage.php` | ソース | Facadeクラス |
| StreamedResponse.php | `vendor/symfony/http-foundation/StreamedResponse.php` | ソース | Symfony基底クラス |
| Str.php | `src/Illuminate/Support/Str.php` | ソース | ascii()メソッド |
