上传单个分块
发送分块上传的一个分块(PUT /v1/objects/chunked):原始字节,除最后一块外每块 5 到 32 MB,顺序任意,失败后可安全重试。
curl --request PUT \
--url 'https://blob.squarecloud.app/v1/objects/chunked?upload=UPLOAD_TOKEN&part=1' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/octet-stream' \
--data-binary '@./chunk-1.bin'
const PART_SIZE = 16 * 1024 * 1024;
const total = Math.ceil(file.size / PART_SIZE);
async function sendPart(n) {
const body = file.slice((n - 1) * PART_SIZE, n * PART_SIZE);
const params = new URLSearchParams({ upload: uploadToken, part: String(n) });
const res = await fetch(`https://blob.squarecloud.app/v1/objects/chunked?${params}`, {
method: 'PUT',
headers: { Authorization: 'YOUR_API_KEY', 'Content-Type': 'application/octet-stream' },
body,
});
if (res.status === 429 || res.status >= 500) return sendPart(n); // add a backoff in production
if (!res.ok) throw new Error((await res.json()).code);
}
// 6 workers, each taking the next part number
let next = 1;
await Promise.all(Array.from({ length: 6 }, async () => {
while (next <= total) await sendPart(next++);
}));
import requests
with open('./bigfile.bin', 'rb') as f:
chunk = f.read(16 * 1024 * 1024)
response = requests.put(
'https://blob.squarecloud.app/v1/objects/chunked',
headers={'Authorization': 'YOUR_API_KEY', 'Content-Type': 'application/octet-stream'},
params={'upload': upload_token, 'part': 1},
data=chunk,
)
{
"status": "success",
"response": {
"part": 1,
"size": 16777216,
"etag": "\"9bb58f26192e4ba00f01e2e7b136bbd8\""
}
}
分块发送用于发送通过分块初始化开启的上传中的一个分块。请求体是该分块的原始字节,而不是 multipart/form-data。分块编号从 1 到 2048,可以按任意顺序发送。以相同编号重新发送分块会替换原分块,因此失败的分块直接重试即可。
除最后一个分块外,每个分块必须在 5 MB 到 32 MB 之间;最后一个可以更小。每个账户最多并行发送 6 个分块:第七个会返回
TOO_MANY_CONCURRENT_CHUNKS,你可以在另一个分块完成后重试该分块。在 6 个并行传输的情况下,16 MB 的分块是浏览器的一个不错的默认值。
该路由有自己的限制,每 10 秒 60 个分块,并且不消耗账户级 API 预算,因此长时间的上传不会耗尽你在平台其他部分的 API 配额。需要 blob:write scope,或开启该上传的上传令牌,以及有效计划。
参数
string
必填
分块初始化返回的
upload 令牌。number
必填
分块编号,从 1 到 2048。
binary
必填
分块的原始字节(
Content-Type: application/octet-stream)。响应
string
成功为 “success”,否则为 “error”。
curl --request PUT \
--url 'https://blob.squarecloud.app/v1/objects/chunked?upload=UPLOAD_TOKEN&part=1' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/octet-stream' \
--data-binary '@./chunk-1.bin'
const PART_SIZE = 16 * 1024 * 1024;
const total = Math.ceil(file.size / PART_SIZE);
async function sendPart(n) {
const body = file.slice((n - 1) * PART_SIZE, n * PART_SIZE);
const params = new URLSearchParams({ upload: uploadToken, part: String(n) });
const res = await fetch(`https://blob.squarecloud.app/v1/objects/chunked?${params}`, {
method: 'PUT',
headers: { Authorization: 'YOUR_API_KEY', 'Content-Type': 'application/octet-stream' },
body,
});
if (res.status === 429 || res.status >= 500) return sendPart(n); // add a backoff in production
if (!res.ok) throw new Error((await res.json()).code);
}
// 6 workers, each taking the next part number
let next = 1;
await Promise.all(Array.from({ length: 6 }, async () => {
while (next <= total) await sendPart(next++);
}));
import requests
with open('./bigfile.bin', 'rb') as f:
chunk = f.read(16 * 1024 * 1024)
response = requests.put(
'https://blob.squarecloud.app/v1/objects/chunked',
headers={'Authorization': 'YOUR_API_KEY', 'Content-Type': 'application/octet-stream'},
params={'upload': upload_token, 'part': 1},
data=chunk,
)
{
"status": "success",
"response": {
"part": 1,
"size": 16777216,
"etag": "\"9bb58f26192e4ba00f01e2e7b136bbd8\""
}
}
错误
| 代码 | HTTP | 触发情况 |
|---|---|---|
INVALID_UPLOAD_TOKEN | 400 | upload 令牌缺失、格式错误或不属于你。 |
INVALID_CHUNK_PART | 400 | part 不是 1 到 2048 之间的整数。 |
EMPTY_CHUNK | 400 | 请求体为空。 |
PERMISSION_DENIED | 401 | 账户没有有效计划。 |
UPLOAD_NOT_FOUND | 404 | 该上传已完成、已中止或已过期。 |
CHUNK_TOO_LARGE | 413 | 分块超过 32 MB。 |
FILE_TOO_LARGE | 413 | 加上这个分块后,上传超出了其大小限制。 |
TOO_MANY_CONCURRENT_CHUNKS | 429 | 已有 6 个分块正在传输。请在其中一个完成后重试该分块。 |
RATE_LIMITED | 429 | 10 秒内超过 60 个分块。 |
UPLOAD_FAILED | 500 | 该分块失败。请重试。 |
相关内容
- Blob SDK:
blob.put()会为超过 90 MiB 的文件自动执行完整的分块上传流程
⌘I
curl --request PUT \
--url 'https://blob.squarecloud.app/v1/objects/chunked?upload=UPLOAD_TOKEN&part=1' \
--header 'Authorization: YOUR_API_KEY' \
--header 'Content-Type: application/octet-stream' \
--data-binary '@./chunk-1.bin'
const PART_SIZE = 16 * 1024 * 1024;
const total = Math.ceil(file.size / PART_SIZE);
async function sendPart(n) {
const body = file.slice((n - 1) * PART_SIZE, n * PART_SIZE);
const params = new URLSearchParams({ upload: uploadToken, part: String(n) });
const res = await fetch(`https://blob.squarecloud.app/v1/objects/chunked?${params}`, {
method: 'PUT',
headers: { Authorization: 'YOUR_API_KEY', 'Content-Type': 'application/octet-stream' },
body,
});
if (res.status === 429 || res.status >= 500) return sendPart(n); // add a backoff in production
if (!res.ok) throw new Error((await res.json()).code);
}
// 6 workers, each taking the next part number
let next = 1;
await Promise.all(Array.from({ length: 6 }, async () => {
while (next <= total) await sendPart(next++);
}));
import requests
with open('./bigfile.bin', 'rb') as f:
chunk = f.read(16 * 1024 * 1024)
response = requests.put(
'https://blob.squarecloud.app/v1/objects/chunked',
headers={'Authorization': 'YOUR_API_KEY', 'Content-Type': 'application/octet-stream'},
params={'upload': upload_token, 'part': 1},
data=chunk,
)
{
"status": "success",
"response": {
"part": 1,
"size": 16777216,
"etag": "\"9bb58f26192e4ba00f01e2e7b136bbd8\""
}
}

