API 文档 公开页面 无需登录

多账号 Cloudflare R2 聚合图床 · 上传 / 直链 / 管理 · 统一短链 · 轮询分发

新号接入:Cloudflare 侧设置(6 步)

步骤操作入口不做会怎样
1开通 R2 计划(免费)控制台左侧 R2无法建桶
2绑定支付方式(信用卡/PayPal)结算 → 付款方式R2 用不了(免费额度内不扣费但必须绑卡)
3创建存储桶R2 → 概述 → 创建存储桶
4开启公共访问桶 → 设置 → 公共访问 → 允许访问(r2.dev)链接全部 404!最常漏的一步
5创建 API 令牌(对象读和写)R2 → 管理 R2 API 令牌平台无法上传
6复制 Account ID + AK + Secret 到本平台Secret 只显示一次
📌 建议顺手做:每个账号绑卡后在「结算 → 通知」加预算告警(如 $0.5),超额立刻收邮件;开启两步验证防封号。
💡 批量接入用控制台「批量导入」行格式:名称|AccountID|AK|SK|桶名|公开域名 一行一号。

❓ 这些参数怎么获取?

全程在 Cloudflare 控制台操作:dash.cloudflare.com ↗

① Account ID(账号 ID)
登录 Cloudflare 控制台 → 左侧「R2 对象存储」→ 概述页右侧「帐户详情」面板 → 复制帐户 ID。填入后 endpoint 自动拼好,不用手动填。
② Access Key ID / Secret Access Key
R2 概述页 → 右上角「管理 R2 API 令牌」→「创建 API 令牌」→ 权限选对象读和写,范围选「仅应用于特定桶」并勾选你的桶 → 创建后显示两串值。Secret 只显示这一次,立即复制保存!
③ bucket(R2 桶名)
R2 →「概述」→ 创建存储桶时起的名字。一个账号可建多个桶,每个桶在本平台算一条记录。
④ 公开访问域名 public_base_url(推荐配置)
进入你的桶 →「设置」→「公共访问」:方式 A 点允许访问开启 r2.dev 子域,复制形如 https://pub-xxxx.r2.dev;方式 B 绑定自定义域名(需域名托管在同一 CF 账号)。不开公共访问 = 链接全部 404!
⑤ 名称 label / 自定义 endpoint / Path Style
label 是自己起的唯一代号(acc01、acc02…),用于轮询分发和短链展示;endpoint 留空自动按 Account ID 拼 R2 地址(只有接 MinIO 才填);Path Style 保持默认「是」。

鉴权方式

除标注 公开 的接口外,所有请求需带请求头:

Authorization: Bearer <你的密钥>
密钥类型获取方式权限
API 密钥
r2h_xxx...
控制台 →「API 密钥」→ 新建(完整值只显示一次)上传 / 预签名 / 确认,推荐程序使用
管理员 Token部署时 ADMIN_TOKEN 环境变量全部接口(含桶管理、巡检)

接口总览

接口鉴权说明
GET/health公开健康检查
POST/uploadAPI Keymultipart 上传单张图片
POST/api/presignAPI Key获取预签名直传地址(推荐)
PUT{upload_url}签名自带直传字节到 Cloudflare
POST/api/presign/confirmAPI Key可选:回报真实大小
GET/b/{key}公开统一短链,302 跳转或代理输出
GET/f/{label}/{key}公开指定桶的代理下载
GET/api/images管理员上传记录分页列表
DEL/api/images/{id}管理员删除记录并删除云端对象
POST/api/buckets/bulk管理员批量导入桶配置(JSON 数组)
POST/api/buckets/check_all管理员手动触发全量巡检,死号自动停用
GET/api/keys管理员API 密钥增删改查(见控制台)

方式一:直接上传(简单)

curl -X POST http://你的地址:8100/upload \
  -H "Authorization: Bearer r2h_你的密钥" \
  -F "file=@cat.jpg"

响应:

{
  "id": 42,
  "url": "https://pub-xxxx.r2.dev/images/20260825/18f3a1b2c3.jpg",
  "short_url": "http://你的地址:8100/b/images/20260825/18f3a1b2c3.jpg",
  "proxied_url": "http://你的地址:8100/f/account01/images/20260825/18f3a1b2c3.jpg",
  "bucket": "account01",
  "key": "images/20260825/18f3a1b2c3.jpg",
  "size": 102400,
  "filename": "cat.jpg"
}
💡 不指定桶时自动在所有启用且未满的桶之间轮询分发;某号临时故障自动换下一个重试。也可 ?bucket=acc01 强制指定。

方式二:预签名直传(推荐,省 VPS 流量)

图片字节不经过服务器,直接从你的程序进 Cloudflare。

import requests

BASE = "http://你的地址:8100"
H = {"Authorization": "Bearer r2h_你的密钥"}

# 第1步:要签名地址
p = requests.post(f"{BASE}/api/presign", headers=H,
                  json={"filename": "gen.png", "size": len(img)}).json()

# 第2步:直传 Cloudflare(签名 15 分钟内有效)
requests.put(p["upload_url"], data=img,
             headers={"Content-Type": "image/png"})

# 第3步:拿到永久链接
print(p["short_url"])   # 统一短链
print(p["url"])         # 最终直链
presign 请求字段必填说明
filename原始文件名,决定扩展名
size建议传文件字节数,用于容量配额预判
content_type如 image/png;传了则 PUT 必须带相同 Content-Type 头
bucket强制指定桶 label;不传走轮询
⚠️ 签名 URL 有效期 900 秒,只能对返回的 key 做一次 PUT。confirm 可选:POST /api/presign/confirm {"key":"...","size":12345}
字段形式适用
short_url/b/{key},302 跳转对外分享首选:统一域名、隐藏真实桶、带浏览器缓存
url桶的公开域名直链已知并信任该桶时少一跳
proxied_url/f/{桶}/{key}桶未绑定公开域名时的代理通道

错误码

状态码含义
400参数缺失 / 没有可用桶
401密钥无效或被停用
413超过 MAX_UPLOAD_MB 上限
502所有候选桶均失败 / 签名生成失败(详情见 detail 字段)

PicGo 自定义图床配置

API 地址http://你的地址:8100/upload
POST 参数名file
JSON 路径url(想要短链就填 short_url
自定义请求头{"Authorization": "Bearer r2h_你的密钥"}

R2 Hub v1.1 · 单用户多账号 R2 聚合图床 · 轮询分发 / 故障切换 / 容量配额 / 自动巡检