各画像生成フォームの presigned URL 直アップロード化(横展開)

done

セッション開始:2026/06/10 07:22

※ ホームステージングを含む横断改修のため、代表として本機能配下にセッションを配置。対象各機能のドキュメントから本ページへリンクしています。

planning developing done

目的 / なぜ必要か

3D間取りで先行導入したクライアント直アップロード(presigned URL 方式)を、 他の画像生成5機能(ホームステージング / DIYリフォーム / 家具消し / 家具引越し / 居抜き)の新規作成フォームへ横展開する。

従来、これらのフォームは入力画像を base64 でサーバーアクションに送り、サーバー側で S3 へアップロードしていた。 この経路では大きな base64 ペイロードが WAF の検査・VPC のデータ転送・ECS の処理を通過するため、インフラコストの要因となっていた。 画像の往復を クライアント↔S3 に閉じることで、この経路をなくし VPC / ECS / WAF のコスト削減を図る。

ユーザーから見た操作(画像を選択して「次へ」)は変わらない、純粋なアップロード経路の置き換え

スコープ

やること

  • 5機能の作成フォームで presigned URL を取得し、S3 へ直接 PUT。inputImageUri のみをサーバーアクションへ渡す(3D間取りと同形をインライン展開)
  • new/page.tsx から getAwsCloudfrontEndpoint() をフォームへ渡す
  • サーバーアクションを inputImageUri 専用に統一:使われなくなる inputImage(base64)分岐とサーバー側アップロードを除去
  • 家具消し(cleaning)を標準パターンへ移行:アクションを apps/user/actions/cleaning/ へ移動し action() / Result でラップ
  • 家具引越し(replacement)の S3 キー修正decoratings/(コピペ由来)→ replacements/

やらないこと

  • アップロード処理の共通化(ヘルパー抽出):今回は各フォームへインライン展開。3D間取り(参照元)も現状維持
  • 3D間取りフォームの変更:参照元のため非対象
  • 外装(exterior)の対応:今回の5機能に含まれないため対象外。家具消しと同じ旧パターンが残るため課題化 → 外装 入力画像 直アップロード化
  • getUploadUrlkey 検証(3D間取りセッションから継続中の 既存課題
  • サーバー側 lib/aws/s3/upload の削除(外装など他用途で温存)

アップロードフロー(変更後・各フォーム共通)

  1. PhotoField でファイル選択 →(共通コンポーネント側で JPEG 圧縮)→ { mimeType, data(base64) } を state に保持
  2. フォームで key = {機能プレフィックス}/${MD5(data)}.${ext} を計算(コンテンツアドレス)
  3. getUploadUrl({ key, image: { mimeType } }) で presigned PUT URL を取得
  4. base64 を Blob にデコードして S3 へ PUTcontent-type 一致)
  5. inputImageUri = ${AWS_CLOUDFRONT_ENDPOINT}/${key} を組み立て、createXxx({ inputImageUri }) でレコード作成

⚠️ PUT のボディは base64 文字列のままではなく Blob にデコードして送る。 3D間取りセッションで「base64 テキストがそのまま保存される」重大バグが発生したため、同じ await (await fetch(`data:...;base64,...`)).blob() 方式を踏襲している。

機能別の対応

機能 S3 キー アクション 備考
ホームステージング homestagings/ actions/homestaging/ inputImage 分岐を除去
DIYリフォーム decoratings/ actions/decorating/ inputImage 分岐を除去
家具消し cleanings/ actions/cleaning/ (移動・新設) フォーム内 _actions/ から移動し Result 化。フォームも .success 判定へ
家具引越し replacements/ (修正) actions/replacement/ decoratings/ 誤用を修正。inputImage 分岐を除去
居抜き furnishings/ actions/furnishing/ inputImage 分岐を除去

ホームステージング / DIYリフォーム / 家具引越し / 居抜きのアクションは、もう一方の呼び出し元 components/{機能}-create-button/ が既に inputImageUri を渡していたため、inputImage 分岐の除去は安全に実施できた。

実装内容(影響範囲)

変更 apps/user/app/(vertical)/v/{homestagings,decoratings,cleanings,replacements,furnishings}/new/_components/*-create-form/index.tsx

presigned URL での直アップロードを追加し、inputImageUri をアクションへ渡す。awsCloudFrontEndpoint を props で受領。

変更 apps/user/app/(vertical)/v/{...}/new/page.tsx

5ページで getAwsCloudfrontEndpoint() をフォームへ渡す。

変更 apps/user/actions/{homestaging,decorating,replacement,furnishing}/create-*.ts

入力を inputImageUri のみに統一。inputImage 受け取り・サーバー側アップロード・MD5 計算を除去。replacement はキーを replacements/ へ(ただし生成は不要になりプレフィックスはクライアント側へ移動)。

新規 apps/user/actions/cleaning/create-cleaning.ts

action() / Result でラップし inputImageUri を受領。他機能と構造を揃える。

削除 apps/user/app/(vertical)/v/cleanings/new/_components/cleaning-create-form/_actions/create-cleaning.ts

標準パターンへの移行に伴い削除(actions/cleaning/ へ集約)。フォームの import 参照を差し替え。

検証