🚀

(Firebase)ストレージを使って写真をアップロード

に公開

写真アップロード機能を実装するにあたって、今まではローカルにしか保存したことがなかったため、今回は Firebase を使ってみることにしました。

🔁 実装の流れ

① Firebase プロジェクトを作成

Firebase コンソールから新しいプロジェクトを作成します。


② Storage を有効化

バケットが自動生成されるので、セキュリティルールを設定します。
テストモードまたは本番モードのいずれかで開始)

⭐️ユーザー情報確認のためにはFirebaseで認証できる方法ではないといけない。

✅ 本番モード:認証ユーザーのみにアクセス許可
例:

rules_version = '2';
service firebase.storage {
 match /b/{bucket}/o {
   match /images/{allPaths=**} {
     // ユーザーだけ読み書き可能
     allow read, write: if request.auth != null;
   }
 }
}

③ Firebase SDK の初期化

自分のアプリを Firebase プロジェクトに登録します。
(私は Web アプリだったので Web を選択)

  • SDK 初期化用のファイルを lib/firebase.ts に作成
    アプリを登録すると、「SDK の設定と構成」の部分にインストール命令と初期化に関する文が出てきます!これをlib/firebase.ts 作成します。

⭐️ セキュリティのため、firebaseConfig の情報(API KEYなど)は .env に記述
例:

//直接中身を書かない!
const firebaseConfig = {
  apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
  authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
  measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID, 
};

④ アップロード用コンポーネントを作成

FirebaseのStorageに写真を保存

import { storage } from "@/lib/firebase";
import { getDownloadURL, ref, uploadBytes } from "firebase/storage";

🔹 Firebase ストレージの関数の簡単な説明:

  • ref: 保存するパスを指定(例: "images/myphoto.jpg")
  • uploadBytes: 指定した場所にファイルをアップロード
  • getDownloadURL: アップロードされたファイルのURLを取得(ダウンロードやプレビューに使用)

例:

export default function UploadPhoto() {
    const [file, setFile] = useState<File | null>(null);
    const [uploading, setUploading] = useState(false);
    const [url, setUrl] = useState("");

    const handleUpload = async()=>{
        if(!file) return alert("Please select a file");
       
        try{//UUIDはimport必要!名前重複防止のためなくてもOKfile.nameだけでいい 
            const uniqueFileName = `${uuidv4()}_${file.name}`; 
            const storageRef = ref(storage, `images/${uniqueFileName}`);
            const snapshot = await uploadBytes(storageRef, file);
            const downloadURL = await getDownloadURL(snapshot.ref);
            setUrl(downloadURL);
            alert("File uploaded successfully");
        }catch(error){
            console.error("Error uploading file:", error);
            alert("Error uploading file");
        }finally{
            setUploading(false);
        }
    }


⑤ アップロード後、URL をサーバーへ保存(API)

アップロードされた画像の URL を取得し、API 経由でサーバー・データベース(photo テーブル)に保存。

例:データーベースの操作はPrismaを使ってます。

export async function POST(req: NextRequest) {
            ...省略
    const body = await req.json(); // {photoUrl, postId}をフロント側から取得
    if (!body.photoUrl || !body.postId) {
        return new Response("Invalid request", { status: 400 });
    }

    //PhotoURLをもとに生成
    const photo = await prisma?.photo.create({ 
        data:{
            filename: body.photoUrl,
            postId: body.postId,
            userId: user.userId,
        }
    })

    return new Response(JSON.stringify(photo), { status: 201 });

}

Discussion