vercel-blob について
SDK を使って Vercel Blob オブジェクトストレージを利用する開発者向けスキルです。アップロード、削除、一覧取得、クライアント側やマルチパートのアップロードに加え、一般的な保存パターンを説明します。
主な機能
- 01Blob のアップロード、一覧取得、削除
- 02アップロードトークンを使ったクライアント側アップロード
- 03マルチパートアップロードのパターン
- 04カーソルによる一覧取得とページネーション
- 05一般的なパターンと問題の解決策
活用シーン
- 01ユーザープロフィール画像の保存
- 02非公開ドキュメントのアップロード
- 03ページネーション付き画像ギャラリーの構築
- 04大容量または複数ファイルのアップロード
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill vercel-blobインストール後、Claude Code で/vercel-blobを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/example-template.txtreferences/common-patterns.mdknown-issues.mdscripts/example-script.shtemplates/avatar-upload-flow.tsxdrag-drop-upload.tsxfile-list-manager.tsxpackage.json詳細
Vercel Blob(オブジェクトストレージ)
ステータス:本番環境対応
最終更新日:2025-12-14
依存関係:なし
最新バージョン:@vercel/[email protected]
クイックスタート(3 分)
1. 作成と設定
# In Vercel dashboard: Storage → Create Database → Blob
vercel env pull .env.local
作成されるもの:BLOB_READ_WRITE_TOKEN
2. インストール
bun add @vercel/blob
3. ファイルをアップロード(サーバーアクション)
'use server';
import { put } from '@vercel/blob';
export async function uploadFile(formData: FormData) {
const file = formData.get('file') as File;
const blob = await put(file.name, file, {
access: 'public',
contentType: file.type
});
return blob.url;
}
4. 基本操作
import { put, del, list } from '@vercel/blob';
// Upload
const blob = await put('path/file.jpg', file, { access: 'public' });
// Delete
await del(blob.url);
// List with pagination
const { blobs, cursor } = await list({ prefix: 'uploads/', limit: 100 });
重要なルール
必ず行うこと
| ルール | 理由 |
|---|---|
| クライアント側のアップロードにはクライアントアップロードトークンを使用する | BLOB_READ_WRITE_TOKEN をクライアントに公開しないでください |
contentType を明示的に設定する | PDF や動画をブラウザーで正しく処理するため |
CDN キャッシュには access: 'public' を使用する | プライベートファイルは CDN を経由しません |
| アップロード前にファイルの種類とサイズを検証する | 無効なアップロードを防ぐため |
| パス名で整理する | avatars/、uploads/、documents/ |
| ファイルを置き換える際は古いファイルを削除する | ストレージコストを管理するため |
絶対に行わないこと
| ルール | 理由 |
|---|---|
BLOB_READ_WRITE_TOKEN をクライアントに公開する | セキュリティ上の脆弱性につながります |
| マルチパートを使わずに 500MB を超えるファイルをアップロードする | createMultipartUpload API を使用してください |
| 汎用的なファイル名を使用する | ${Date.now()}-${name} または addRandomSuffix: true を使用してください |
| ファイルの検証を省略する | 必ず種類とサイズを検証してください |
| 機密データを暗号化せずに保存する | アップロード前に暗号化してください |
| ページネーションの処理を忘れる | list() が返すファイルは最大 1000 件です |
既知の問題の予防
このスキルでは、文書化された 10 件の問題を予防できます。
| # | エラー | 簡単な修正方法 |
|---|---|---|
| 1 | BLOB_READ_WRITE_TOKEN not defined | vercel env pull .env.local を実行する |
| 2 | クライアントトークンが公開されている | クライアントアップロードには handleUpload() を使用する |
| 3 | ファイルサイズ超過(500MB) | マルチパートアップロード API を使用する |
| 4 | content-type が誤っている | contentType: file.type を設定する |
| 5 | CDN キャッシュがない | access: 'public' を使用する |
| 6 | リストにファイルが表示されない | カーソルページネーションを使用する |
| 7 | 削除が失敗しても通知されない | put() が返す正確な URL を使用する |
| 8 | アップロードがタイムアウトする | 大きなファイルにはクライアント側アップロードを使用する |
| 9 | ファイル名が重複する | タイムスタンプまたは addRandomSuffix: true を追加する |
| 10 | 状態が更新されない | onUploadCompleted コールバックを使用する |
参照:コード例を含む完全な解決方法については、references/known-issues.md をご覧ください。
よく使われるパターンの概要
| パターン | 用途 | 主な API |
|---|---|---|
| アバターのアップロード | ユーザープロフィール画像 | put、del |
| 保護されたアップロード | プライベートなドキュメント | access: 'private' を指定した put |
| 画像ギャラリー | 一覧表示とページネーション | カーソルを使用した list |
| クライアントアップロード | 大きなファイル、進捗表示 | upload、handleUpload |
| マルチパートアップロード | 500MB を超えるファイル | createMultipartUpload、uploadPart |
| 一括操作 | 複数のファイル | Promise.all、del([...]) |
| 画像処理 | アップロード前の最適化 | sharp + put |
参照:完全な実装については、references/common-patterns.md をご覧ください。
クライアント側アップロード(必須パターン)
サーバーアクション(トークンの生成):
'use server';
import { handleUpload, type HandleUploadBody } from '@vercel/blob/client';
export async function generateUploadToken(body: HandleUploadBody) {
return await handleUpload({
body,
request: new Request('https://dummy'),
onBeforeGenerateToken: async (pathname) => ({
allowedContentTypes: ['image/jpeg', 'image/png', 'image/webp'],
maximumSizeInBytes: 5 * 1024 * 1024
}),
onUploadCompleted: async ({ blob }) => {
// Save to database
await db.insert(uploads).values({ url: blob.url, pathname: blob.pathname });
}
});
}
クライアントコンポーネント:
'use client';
import { upload } from '@vercel/blob/client';
const blob = await upload(file.name, file, {
access: 'public',
handleUploadUrl: '/api/upload'
});
設定
.env.local
# Created by: vercel env pull .env.local
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_xxxxx"
.gitignore
.env.local
.env*.local
参照資料を読み込むタイミング
| 参照資料 | 読み込むタイミング |
|---|---|
references/known-issues.md | アップロードエラー、トークンの問題、CDN キャッシュの問題をデバッグするとき |
references/common-patterns.md | アバターのアップロード、ギャラリー、クライアントアップロード、マルチパートアップロードを実装するとき |
依存関係
{
"dependencies": {
"@vercel/blob": "^2.0.0"
}
}
無料枠の上限:帯域幅は月 100GB、ファイルサイズは最大 500MB
公式ドキュメント
- Vercel Blob:https://vercel.com/docs/storage/vercel-blob
- クライアントアップロード:https://vercel.com/docs/storage/vercel-blob/client-upload
- SDK リファレンス:https://vercel.com/docs/storage/vercel-blob/using-blob-sdk
- GitHub:https://github.com/vercel/storage
トラブルシューティング
| 問題 | 解決策 |
|---|---|
BLOB_READ_WRITE_TOKEN not defined | vercel env pull .env.local を実行します |
| ファイルサイズが上限を超えている(>500MB) | マルチパートアップロード API を使用します |
| クライアントのアップロードに失敗する | サーバー側で handleUpload() を使用します |
| ファイルが削除されない | put() のレスポンスに含まれる正確な URL を使用します |
トークンの節約:~60%(パターンをリファレンスに抽出) エラーの防止:100%(文書化された10件の問題すべて) 本番環境で使用する準備が整いました!
コメント
Markdown 対応