セッション開始:2026/06/10 07:22
※ ホームステージングを含む横断改修のため、代表として本機能配下にセッションを配置。対象各機能のドキュメントから本ページへリンクしています。
3D間取りで先行導入したクライアント直アップロード(presigned URL 方式)を、 他の画像生成5機能(ホームステージング / DIYリフォーム / 家具消し / 家具引越し / 居抜き)の新規作成フォームへ横展開する。
従来、これらのフォームは入力画像を base64 でサーバーアクションに送り、サーバー側で S3 へアップロードしていた。 この経路では大きな base64 ペイロードが WAF の検査・VPC のデータ転送・ECS の処理を通過するため、インフラコストの要因となっていた。 画像の往復を クライアント↔S3 に閉じることで、この経路をなくし VPC / ECS / WAF のコスト削減を図る。
ユーザーから見た操作(画像を選択して「次へ」)は変わらない、純粋なアップロード経路の置き換え。
やること
inputImageUri のみをサーバーアクションへ渡す(3D間取りと同形をインライン展開)new/page.tsx から getAwsCloudfrontEndpoint() をフォームへ渡すinputImageUri 専用に統一:使われなくなる inputImage(base64)分岐とサーバー側アップロードを除去apps/user/actions/cleaning/ へ移動し action() / Result でラップdecoratings/(コピペ由来)→ replacements/やらないこと
getUploadUrl の key 検証(3D間取りセッションから継続中の
既存課題)lib/aws/s3/upload の削除(外装など他用途で温存)PhotoField でファイル選択 →(共通コンポーネント側で JPEG 圧縮)→ { mimeType, data(base64) } を state に保持key = {機能プレフィックス}/${MD5(data)}.${ext} を計算(コンテンツアドレス)getUploadUrl({ key, image: { mimeType } }) で presigned PUT URL を取得Blob にデコードして S3 へ PUT(content-type 一致)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 参照を差し替え。
tsc --noEmit(apps/user)エラー 0_actions/create-cleaning への参照が残っていないこと、5フォームが inputImageUri を渡していることを grep で確認ff d8 ff …=正常 JPEG)確認は、3D間取りで検証済みの同一フロー・同一 Blob 化方式を踏襲