-
Notifications
You must be signed in to change notification settings - Fork 1
Closed
Labels
Description
概要
- Cloudflare R2 セットアップ
- 共通アップロードシステム
- アバター + イベント画像対応
- 既存のURL入力も継続サポート
- 共通コンポーネント化
実装範囲
- Cloudflare R2 統合
- 共通アップロードAPI
- 統一UI コンポーネント
- 画像最適化・リサイズ
- プログレス表示
- エラーハンドリング
- 既存URL入力との共存
- アバター + イベント画像対応
メモ
// 共通アップロード機能
functions/api/upload/
├── image.ts // 汎用画像アップロード
├── avatar.ts // アバター専用(リサイズ付き)
└── event-image.ts // イベント画像専用
統合実装のメリット
技術的メリット
共通化できるもの:
✅ Cloudflare R2設定
✅ 画像バリデーション(サイズ・形式)
✅ ファイル名生成ロジック
✅ エラーハンドリング
✅ プレビュー機能
✅ セキュリティチェック
開発効率のメリット
一度の学習で:
✅ R2 SDK の習得
✅ ファイルアップロードパターン
✅ 画像処理ライブラリ
✅ プログレス表示UI
✅ エラー処理パターン
ユーザー体験のメリット
一貫したUX:
✅ 同じアップロード操作
✅ 統一されたプレビュー
✅ 同じエラーメッセージ
✅ 同じプログレス表示
構成案
共通コンポーネント設計
// src/components/ImageUpload.tsx
interface ImageUploadProps {
type: 'avatar' | 'event';
currentUrl?: string;
onUploadComplete: (url: string) => void;
maxSize?: number;
aspectRatio?: number;
}
export function ImageUpload({ type, currentUrl, onUploadComplete }: ImageUploadProps) {
// 共通ロジック:
// - ドラッグ&ドロップ
// - ファイル検証
// - アップロード処理
// - プレビュー表示
// - エラーハンドリング
}
バックエンド共通化
// functions/api/utils/image-upload.ts
export async function uploadImage(
file: File,
type: 'avatar' | 'event',
userId: string,
env: Env
): Promise<string> {
// 共通処理:
// - ファイル検証
// - リサイズ(必要に応じて)
// - R2アップロード
// - URL生成
const folder = type === 'avatar' ? 'avatars' : 'events';
const key = `${folder}/${userId}/${createId()}-${file.name}`;
await env.R2_BUCKET.put(key, file.stream());
return `https://your-r2-domain.com/${key}`;
}
互換性の維持
// URL入力を残す
interface ImageInputProps {
mode: 'url' | 'upload' | 'both';
}
// 段階的移行
<ImageInput
mode="both" // URLとアップロード両方対応
currentUrl={event.image_url}
onUrlChange={handleUrlChange}
onFileUpload={handleFileUpload}
/>
パフォーマンス考慮
// 画像の最適化設定
const imageConfig = {
avatar: {
maxWidth: 256,
maxHeight: 256,
quality: 85
},
event: {
maxWidth: 800,
maxHeight: 600,
quality: 80
}
};
ブランチ
feature/image-upload-integration