上传 API
上传 API 支持通过第三方上传文件至 CloudFlare ImgBed,便于集成到各种应用和服务中。
基本信息
- 端点:
/upload - 方法:
POST - 认证:上传认证码或 API Token(需要
upload权限) - 内容类型:
multipart/form-data
响应格式
[{ "src": "/file/abc123_image.jpg" }]src 不包含域名,需自行拼接。使用 returnFormat=full 可返回完整链接。
普通上传
直接通过 /upload 端点上传文件,适用于小文件。
参数
Query 参数:
| 参数名 | 类型 | 必需 | 默认值 | 说明 |
|---|---|---|---|---|
authCode | string | 否 | - | 上传认证码 |
uploadChannel | string | 否 | telegram | 上传渠道:telegram、cfr2、s3、discord、huggingface、webdav |
channelName | string | 否 | - | 指定渠道名称(多渠道场景),可通过 /api/channels 获取可用列表 |
serverCompress | boolean | 否 | true | 服务端压缩(仅 Telegram 渠道图片) |
autoRetry | boolean | 否 | true | 失败时自动切换渠道重试 |
uploadNameType | string | 否 | default | 命名方式:default(前缀_原名)、index(仅前缀)、origin(仅原名)、short(短链接) |
returnFormat | string | 否 | default | 返回格式:default(/file/id)、full(完整链接) |
uploadFolder | string | 否 | - | 上传目录,相对路径,如 img/test |
Body 参数(FormData):
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
file | File | 是 | 要上传的文件 |
示例
curl -X POST 'https://your.domain/upload?authCode=YOUR_CODE&uploadChannel=telegram' \
-F 'file=@"/path/to/image.jpg"'文件大小限制
- Cloudflare Pages 部署:单次请求体上限 100MB
- Telegram 渠道:单文件上限 20MB(超过自动服务端分片)
- Discord 渠道:免费 10MB / Nitro 25MB
- HuggingFace 渠道:普通上传走后端代理,受 CF Workers CPU 时间限制,建议大文件使用直传方式(见下文)
分块上传(Telegram / R2 / S3 / Discord)
当文件较大时,客户端可将文件切分为多个分块,逐块上传后由服务端合并。适用于 telegram、cfr2、s3、discord 四个渠道。
HuggingFace 渠道不支持分块上传
HuggingFace 渠道有独立的大文件直传流程,请参考下方 HuggingFace 大文件直传 章节。
推荐分块大小
| 渠道 | 推荐分块大小 | 说明 |
|---|---|---|
telegram | 16MB | Telegram Bot getFile 下载限制 20MB,留 4MB 安全余量 |
cfr2 / s3 | 5MB - 20MB | 遵循 S3 Multipart Upload 规范,最小 5MB |
discord | 8MB | 免费用户 10MB 限制,留余量 |
上传流程
分块上传分为三步:初始化 → 逐块上传 → 合并。
第一步:初始化
创建上传会话,获取 uploadId。
Query 参数:
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
authCode | string | 否 | 上传认证码 |
initChunked | boolean | 是 | 固定为 true |
uploadChannel | string | 否 | 上传渠道:telegram、cfr2、s3、discord |
channelName | string | 否 | 指定渠道名称(多渠道场景),可通过 /api/channels 获取可用列表 |
Body 参数(FormData):
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
originalFileName | string | 是 | 原始文件名 |
originalFileType | string | 是 | 原始文件 MIME 类型 |
totalChunks | integer | 是 | 分块总数 |
请求示例:
POST /upload?authCode=YOUR_CODE&initChunked=true&uploadChannel=telegram
Content-Type: multipart/form-data
FormData:
originalFileName: "video.mp4"
originalFileType: "video/mp4"
totalChunks: 5响应示例:
{
"success": true,
"uploadId": "upload_1713500000000_abc123def",
"sessionInfo": {
"uploadId": "upload_1713500000000_abc123def",
"originalFileName": "video.mp4",
"totalChunks": 5,
"uploadChannel": "telegram"
}
}第二步:逐块上传
将文件按推荐大小切分,依次上传每个分块。每个请求是同步的,服务端会等待分块上传到存储端后才响应。
Query 参数:
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
authCode | string | 否 | 上传认证码 |
chunked | boolean | 是 | 固定为 true |
uploadChannel | string | 否 | 上传渠道:telegram、cfr2、s3、discord |
channelName | string | 否 | 指定渠道名称(多渠道场景),可通过 /api/channels 获取可用列表 |
Body 参数(FormData):
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
file | File | 是 | 分块二进制数据 |
uploadId | string | 是 | 初始化返回的上传会话 ID |
chunkIndex | integer | 是 | 分块索引,从 0 开始 |
totalChunks | integer | 是 | 分块总数 |
originalFileName | string | 是 | 原始文件名 |
originalFileType | string | 是 | 原始文件 MIME 类型 |
请求示例:
POST /upload?authCode=YOUR_CODE&chunked=true&uploadChannel=telegram
Content-Type: multipart/form-data
FormData:
file: <分块二进制数据>
uploadId: "upload_1713500000000_abc123def"
chunkIndex: 0
totalChunks: 5
originalFileName: "video.mp4"
originalFileType: "video/mp4"响应示例:
{
"success": true,
"message": "Chunk 1/5 received and being uploaded",
"uploadId": "upload_1713500000000_abc123def",
"chunkIndex": 0
}并发上传
各分块可并发上传以提升速度。对于 R2/S3 渠道,第一个分块(chunkIndex=0)会初始化 Multipart Upload,其他分块会自动等待初始化完成(最多等待 60 秒)。
第三步:合并
所有分块上传完成后,请求合并。合并过程是同步的。
Query 参数:
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
authCode | string | 否 | 上传认证码 |
chunked | boolean | 是 | 固定为 true |
merge | boolean | 是 | 固定为 true |
uploadChannel | string | 否 | 上传渠道:telegram、cfr2、s3、discord |
channelName | string | 否 | 指定渠道名称(多渠道场景),可通过 /api/channels 获取可用列表 |
returnFormat | string | 否 | 返回格式:default(/file/id)、full(完整链接) |
uploadFolder | string | 否 | 上传目录,相对路径,如 img/test |
Body 参数(FormData):
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
uploadId | string | 是 | 上传会话 ID |
totalChunks | integer | 是 | 分块总数 |
originalFileName | string | 是 | 原始文件名 |
originalFileType | string | 是 | 原始文件 MIME 类型 |
请求示例:
POST /upload?authCode=YOUR_CODE&chunked=true&merge=true&uploadChannel=telegram
Content-Type: multipart/form-data
FormData:
uploadId: "upload_1713500000000_abc123def"
totalChunks: 5
originalFileName: "video.mp4"
originalFileType: "video/mp4"响应示例:
[{ "src": "/file/1713500000000_video.mp4" }]失败重试
合并时服务端会自动检查各分块状态,对失败或超时的分块进行重试(最多 5 次)。如果仍有分块未完成,合并会返回错误。
清理请求
如果上传中途取消,可发送清理请求释放临时数据。
Query 参数:
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
authCode | string | 否 | 上传认证码 |
cleanup | boolean | 是 | 固定为 true |
uploadId | string | 是 | 上传会话 ID |
totalChunks | integer | 是 | 分块总数 |
POST /upload?authCode=YOUR_CODE&cleanup=true&uploadId=xxx&totalChunks=5HuggingFace 大文件直传
HuggingFace 渠道采用独立的上传流程,文件由客户端直接上传到 HuggingFace LFS 存储,CF Workers 仅负责签名和提交,从而绕过 Cloudflare 的 100MB 请求体限制和 CPU 时间限制。
上传方式选择
| 场景 | 方式 | 说明 |
|---|---|---|
| 小文件(< 20MB) | 普通上传 /upload?uploadChannel=huggingface | 文件经由后端代理上传 |
| 大文件(≥ 20MB) | 直传流程(三步) | 客户端直传 HuggingFace S3,后端只做签名和提交 |
直传流程
前置准备
客户端需要预先计算:
- SHA-256:文件完整内容的 SHA-256 哈希(hex 字符串)
- fileSample:文件前 512 字节的 Base64 编码
第一步:获取上传 URL
请求参数(JSON Body):
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
fileName | string | 是 | 文件名 |
fileType | string | 是 | 文件 MIME 类型 |
fileSize | integer | 是 | 文件大小(字节) |
sha256 | string | 是 | 文件 SHA-256 哈希(hex) |
fileSample | string | 是 | 文件前 512 字节的 Base64 |
channelName | string | 否 | 指定渠道名称(多渠道场景),可通过 /api/channels 获取可用列表 |
uploadNameType | string | 否 | 命名方式:default(前缀_原名)、index(仅前缀)、origin(仅原名)、short(短链接) |
uploadFolder | string | 否 | 上传目录,相对路径,如 img/test |
请求示例:
POST /upload/huggingface/getUploadUrl
Content-Type: application/json
Authorization: Bearer <API_TOKEN>
{
"fileName": "large-video.mp4",
"fileType": "video/mp4",
"fileSize": 524288000,
"sha256": "e3b0c44298fc1c149afbf4c8996fb924...",
"fileSample": "AAAAIGZ0eXBpc29t...",
"channelName": "my-hf-channel",
"uploadNameType": "default",
"uploadFolder": "videos"
}响应示例:
{
"success": true,
"fullId": "videos/1713500000000_large-video.mp4",
"filePath": "videos/a1b2c3d4_1713500000000_large-video.mp4",
"channelName": "my-hf-channel",
"repo": "username/repo-name",
"needsLfs": true,
"alreadyExists": false,
"oid": "e3b0c44298fc1c149afbf4c8996fb924...",
"uploadAction": {
"href": "https://s3.amazonaws.com/...",
"header": { ... }
}
}关键字段说明:
needsLfs: false:文件无需 LFS(极小的文本文件),直接跳到第三步提交alreadyExists: true:文件已存在于 LFS,跳过第二步直接提交uploadAction.header.chunk_size:如果存在此字段,说明 HuggingFace 要求分片上传,header中的零填充数字键("00001","00002", ...)为各分片的预签名上传 URL
第二步:上传文件到 HuggingFace S3
根据 uploadAction 返回的信息,客户端直接上传到 HuggingFace 的 S3 存储。
基本上传(无 chunk_size):
PUT <uploadAction.href>
Headers: <uploadAction.header>
Body: <文件二进制内容>分片上传(有 chunk_size):
将文件按 chunk_size 切分,依次 PUT 到 header["00001"]、header["00002"] ... 对应的 URL,收集每个响应的 ETag。全部上传完成后,POST 到 uploadAction.href 完成合并:
POST <uploadAction.href>
Content-Type: application/vnd.git-lfs+json
{
"oid": "<sha256>",
"parts": [
{ "partNumber": 1, "etag": "\"abc123\"" },
{ "partNumber": 2, "etag": "\"def456\"" }
]
}第三步:提交文件引用
上传完成后,调用提交接口将文件注册到系统数据库。
请求参数(JSON Body):
| 参数名 | 类型 | 必需 | 说明 |
|---|---|---|---|
fullId | string | 是 | 第一步返回的文件 ID |
filePath | string | 是 | 第一步返回的存储路径 |
sha256 | string | 是 | 文件 SHA-256 哈希(hex) |
fileSize | integer | 是 | 文件大小(字节) |
fileName | string | 否 | 文件名 |
fileType | string | 否 | 文件 MIME 类型 |
channelName | string | 否 | 指定渠道名称(多渠道场景),可通过 /api/channels 获取可用列表 |
请求示例:
POST /upload/huggingface/commitUpload
Content-Type: application/json
Authorization: Bearer <API_TOKEN>
{
"fullId": "videos/1713500000000_large-video.mp4",
"filePath": "videos/a1b2c3d4_1713500000000_large-video.mp4",
"sha256": "e3b0c44298fc1c149afbf4c8996fb924...",
"fileSize": 524288000,
"fileName": "large-video.mp4",
"fileType": "video/mp4",
"channelName": "my-hf-channel"
}响应示例:
{
"success": true,
"src": "/file/videos/1713500000000_large-video.mp4",
"fileUrl": "https://huggingface.co/datasets/username/repo-name/resolve/main/videos/a1b2c3d4_1713500000000_large-video.mp4",
"fullId": "videos/1713500000000_large-video.mp4"
}流程总结

