2026年3月31日
メール提供から直接アップロードへ
写真のメール投稿をユーザーの直接アップロードへ移行。
導入
ゲームセンターデータ
#ゲームセンター情報
eric

Betaでゲームセンターの写真を投稿するには、メールにファイルを添付する必要があった。運営者が内容を確認し、添付をダウンロードしてサービスへ手作業で登録していた。ギャラリーで写真を表示できても、利用者自身のアップロード経路はまだなかったのである。Deltaではサイトで直接写真を受け取り、メールで集まった資料も新しい保存方式へ移した。

メール投稿と保存容量

ファイル選択画面だけを見ると、直接アップロードは簡単に思える。しかし写真は、一度受信すれば処理が終わる資料ではない。投稿が増えるたびに保存容量を使い、ギャラリーが開かれるたびに転送量も発生する。そこで受付を始める前に、増え続けるファイルをどこに置き、どう配信するかを準備した。S3の接続方法と、多数のファイルを運用する方法を学ぶ必要があった。

S3はファイルをオブジェクトとして保存するストレージである。サーバーのディスクへ写真を蓄積し続ける代わりに、外部の保存領域を利用できる。ただし、保存先を変えるだけでは足りない。メールを読む運営者が把握していた「どの店舗の写真で、誰が送ったか」を、今度はサーバーがデータとして持たなければならないからだ。

Mermaid
flowchart TD
    accTitle: メール受付からサイトへのアップロードへ
    accDescr: 以前は運営者がメール添付を手動登録した。直接アップロードではサーバーがファイルを検査し保存先と文書記録を結ぶ。
    U[利用者の写真] --> M[メール提供]
    M --> O[運営者の確認と手動登録]
    U --> W[サイトへの直接アップロード]
    W --> B[サーバーの検査と記録作成]
    B --> S[S3へのファイル保管]
    B --> R[店舗と作成者の関連付け]

写真アップロードとS3ストレージ

S3の接続では、まずバケットという保存領域を用意する。PocketBaseのファイル保存設定にバケット名、リージョン、エンドポイント、認証情報を入れて有効化すると、PocketBaseのファイルシステムがその領域を使う。ローカル保存と同じファイル処理を通るため、画面側が保存先のURLや秘密鍵を直接管理する必要はない。

写真を選ぶと、ブラウザーは店舗IDとファイルをmultipart形式でサーバーへ送る。multipartは通常の入力値とファイルを一つのリクエストにまとめる方式だ。サーバーが内容を検査して写真レコードのファイル欄へ保存すると、実際のファイル保管は設定済みのPocketBaseストレージが担う。S3認証情報をブラウザーへ渡してバケットを直接操作させる方式にはしなかった。

保存設定の確認では、アップロードから店舗詳細で再び開くところまで試す必要がある。DB上のファイル名とS3の実際の位置が合わなければ、送信が終わってもギャラリーには表示されない。また、写真ファイルとデータベースのバックアップは、それぞれ保存設定が必要だ。写真を保管できてもDBのバックアップまで整ったことにはならない。

アップロード写真の公開手順

複数の写真を一度に送る場合、一部だけ成功することもある。アップロードAPIの/arcade/photo/uploadは、成功したファイルごとにarcade_photo_atomsレコードを作り、店舗と作成者とファイルを結び付けて非公開で保管する。レスポンスでは成功したレコードIDと失敗したファイルを分け、実際の結果を確認できるようにした。

ファイル送信後には、文書で使う写真一覧を決める。/arcade/photoが選択写真の店舗への所属を確認して公開状態に変え、ID一覧を持つarcade_photoレコードを作る。現在の写真参照と履歴も一緒に更新する。この確定処理をDBトランザクションでまとめることで、一覧の一部だけが変わった文書を残さずに済む。送った写真から公開するものを選べるのも、この二段階によるものだ。

Mermaid
sequenceDiagram
    accTitle: ファイル保管と文書公開の二段階
    accDescr: アップロードは非公開写真レコードを作る。一覧の保存では店舗との対応を確認し公開一覧と現在の参照を確定する。
    participant U as 利用者
    participant B as サーバー
    participant S as ファイル保存先
    participant D as データベース
    U->>B: 写真ファイルをアップロード
    B->>S: ファイルを保管
    B->>D: 非公開写真レコードを作成
    B-->>U: 成功IDと失敗項目
    U->>B: 選択した写真IDを保存
    B->>D: 店舗を確認し公開一覧と参照と履歴を更新
    B-->>U: 文書への反映結果

メール写真の移行と出典

直接投稿へ移っても、既存のメール投稿は引き続き使う必要があった。メールには写真だけでなく、対象店舗、投稿者、受信時刻も残っている。ファイルだけコピーすれば投稿の背景を失い、メール情報だけ移せばギャラリーで表示する写真がない。

対象メールの添付と情報はMail AppleScriptで取り出した。ArcadeIDで場所、UIDで投稿者、Received_atで元の受信時刻を結び付ける。写真ごとのレコードとID一覧を持つまとまりを作り、ファイルはコレクションID、写真レコードID、ファイル名に合ったパスで準備してS3オブジェクトと接続した。過去の投稿が移行日に新規投稿されたように見えないよう、受信時刻も維持した。

同じメールを再処理すると写真が重複する可能性がある。移行スクリプトは店舗、受信時刻、投稿者、ファイル名一覧を既存資料と比べ、同じ投稿を除外する。ただし、これは投入済みの資料を探す方法である。写真の店舗や投稿者の対応が正しいかは、元のメール内容と照合する必要がある。

Mermaid
flowchart TD
    accTitle: 写真のファイルと出所を一緒に移す
    accDescr: メールから抽出したファイルを保存オブジェクトに結び、店舗・提供者・元の受付時刻をサービスの記録に残す。
    M[メール添付と提供情報] --> E[AppleScriptで抽出]
    E --> F[ファイルと保存パスを準備]
    E --> I[店舗・提供者・受付時刻]
    F --> S[S3の保存オブジェクト]
    I --> R[写真レコードと写真のまとまり]
    R --> S

直接アップロードによって、すべてのメールを開いてファイルを再登録する作業を減らせた。一方、ファイルを保存しても公開一覧を確定していない状態は生じるため、保管結果と文書への反映結果をそれぞれ扱う必要がある。ファイルがあっても場所の対応を誤れば別のギャラリーへ出てしまう。S3の用意後も、写真の所属と公開状態の管理は続いていく。

参考:Musecatの開発記録。

Musecat
ゲームセンターのすべて