1. HOME
  2. ブログ
  3. エンジニアリング
  4. Next.js × Vercel Blobで画像アップロードを実装

BLOG

ブログ

エンジニアリング

Next.js × Vercel Blobで画像アップロードを実装

本章では、Vercel Blobを導入して画像アップロードを実装していきます。

システム概要のうち以下の部分にあたります。

チュートリアルの全体像

本チュートリアルを通じて学べる内容は以下のようになります。

  1. Next.jsの開発環境をセットアップ
  2. 画面デザインしながら基礎を学ぼう
  3. App Routerを理解して使ってみよう
  4. Next.js+Postgres+PrismaでDB設計
  5. サーバコンポーネントでデータ取得
  6. サーバアクションでデータ変更
  7. Vercel Blobで画像アップロード実装
  8. Suspenseでローディングをリッチに
  9. Zodを使ってバリデーション実装
  10. useActionStateでローディング実装
  11. Auth.js v5で認証機能導入
  12. Route HandlersでAPIを設計

動画で学びたい方はこちらから!

Vercel Blob導入

Blob作成

Storageタブをクリックして、 「Create Database」をクリックします。

Blobを選択してContinueを押しましょう。

名前はそのままでCreateボタンを押します。

Connectボタンを押します。

これでBlobの作成と連携が完了しました。

続いて環境変数を設定していきます。

環境変数設定

再びStorageタブを選択すると、Blobが新しく作成されているので、クリックします。

.env.localのタブをクリックしてください。

「Copy Snippet」ボタンを押して環境変数をコピーします。

最後に .env ファイルに貼り付けます。

これでプロジェクトからBlobにアクセスできるようになりました。

SDKインストール

続いてVercel BlobのSDKをインストールします。

npm i @vercel/blob

Blobに画像をアップロードするときはこちらのSDKを使って行います。

画像アップロード実装

それでは、準備ができたので実際に画像アップロードを実装していきましょう。

投稿作成

lib/actions.ts

import { put } from "@vercel/blob";

/* ... 省略 ... */

export async function createPost(formData: FormData) {
  const email = "user+1@example.com";
  const caption = formData.get("caption") as string;
  const imageFile = formData.get("image") as File;
  const blob = await put(imageFile.name, imageFile, {
    access: "public",
  });

  const user = await prisma.user.findFirstOrThrow({
    where: { email },
  });

  await prisma.post.create({
    data: {
      caption,
      image: blob.url,
      userId: user.id,
    },
  });

  revalidatePath("/dashboard");
  redirect("/dashboard");
}

実際に試してみましょう。

http://localhost:3000/posts/create

に移動して、ファイル選択とキャプションを入力して「公開」ボタンを押しましょう。

実はこのままではエラーが出ます。

Next.jsのImageタグは指定したドメイン以外の画像を読み込まない仕様になっています。

そのため、以下の記述を追加しましょう。

next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "hoyw5roiqu7mak0o.public.blob.vercel-storage.com",
      },
    ],
  },
  experimental: {
    serverActions: {
      bodySizeLimit: "45mb",
    },
  },
};

export default nextConfig;

bodySizeLimitの方は、ServerActionsの最大リクエストサイズの設定です。

デフォルトでは1MBなので、こちらを増やしました。

再び、投稿を作成してみましょう。

正常に投稿ができるはずです。

プロフィールアイコン変更

続いてプロフィールアイコンを変更できるようにしましょう。

lib/actions.ts

export async function updateMe(formData: FormData) {
  const email = "user+1@example.com";
  const user = await prisma.user.findFirstOrThrow({
    where: { email },
  });

  const data = {
    name: formData.get("name") as string,
    description: formData.get("description") as string,
    image: user.image,
  };

  const imageFile = formData.get("image") as File;
  if (imageFile.size > 0) {
    const blob = await put(imageFile.name, imageFile, {
      access: "public",
    });
    data.image = blob.url;
  }

  await prisma.user.update({
    where: { email },
    data,
  });

  revalidatePath("/dashboard");
  redirect("/dashboard");
}

まとめ

以上、Next.jsとVercel Blobを連携して、画像アップロードを実装する方法についてでした!

次回は、ローディング画面を綺麗にする方法を学んでいきます。

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

関連記事