为什么选择 Cloudflare R2?
Cloudflare R2 是 Cloudflare 推出的对象存储服务,最大的优点是没有 egress 流量费用,存储 1GB 免费,1000万请求免费,非常适合个人博客使用。
注册 Cloudflare
访问 Cloudflare 控制台,注册账号并绑定支付方式(免费额度不需要充值)。
创建 R2 Bucket
- 登录 Cloudflare 控制台
- 左侧菜单找到 R2 Object Storage
- 点击"创建存储桶"
- 输入名称,例如 my-blog-images
- 选择地区(推荐自动)
- 点击创建
获取 API 凭证
- 在 R2 控制台点击"管理 API 令牌"
- 点击"创建 API 令牌"
- 选择"编辑 R2 存储桶"
- 设置名称,例如 blog-uploader
- 点击创建
- 保存好显示的 Access Key ID 和 Secret Key
设置自定义域名(可选)
- 返回存储桶设置
- 点击"连接域名"
- 输入子域名,例如 images.yourdomain.com
- 按提示配置 DNS
Next.js 上传图片
安装 AWS SDK:
npm install @aws-sdk/client-s3
创建上传组件(pages/api/upload.js):
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import crypto from "crypto";
const s3 = new S3Client({
region: "auto",
endpoint: `https://<ACCOUNT_ID>.r2.cloudflarestream.com`,
credentials: {
accessKeyId: process.env.R2_ACCESS_KEY_ID,
secretAccessKey: process.env.R2_SECRET_KEY,
},
});
export default async function handler(req, res) {
if (req.method !== "POST") return res.status(405).end();
const buffer = Buffer.from(req.body.image, "base64");
const ext = req.body.extension || "png";
const filename = `${crypto.randomUUID()}.${ext}`;
await s3.send(new PutObjectCommand({
Bucket: "my-blog-images",
Key: filename,
Body: buffer,
ContentType: `image/${ext}`,
}));
res.status(200).json({ url: `https://images.yourdomain.com/${filename}` });
}
设置环境变量
在 .env.local 中添加:
R2_ACCESS_KEY_ID=your_access_key_id
R2_SECRET_KEY=your_secret_key
R2_BUCKET_NAME=my-blog-images
R2_DOMAIN=https://images.yourdomain.com
免费额度说明
- 存储空间:1GB/月 免费
- A 类请求(PUT/POST):1000万次/月 免费
- B 类请求(GET):1000万次/月 免费
- 无 egress 流量收费!
总结
Cloudflare R2 非常适合个人博客图床,免费额度基本够用,而且没有隐藏费用,是目前性价比最高的选择之一。