使用 cURL 进行多部分上传
在本教程中,您将学习如何在 Linux 操作系统上使用 cURL 命令分批上传大文件。 步骤包括在终端窗口中运行拆分,将文件分成几部分,启动上传,上传各个部分,以及完成上传。 此外,本教程使用脚本上传每个文件部分并获取其实体标记(ETag),并生成完成多部分上传操作所需的XML块。
场景
大多数工具,如 CLI 或 IBM Cloud® 控制台,以及大多数兼容库和 SDK,都会以多部分上传的方式自动传输对象。 请参阅 “存储大型物体”了解有关多部分上传操作的详细信息。 在某些情况下,您可能更喜欢使用 cURL 命令进行多部分上传,例如,如果您在只读操作系统中工作,无法安装CLI。
准备工作
在开始上传之前,您需要:
- 一个 IBM Cloud 账户
- IBM Cloud Object Storage 的实例
- 水桶
- 本地系统中大于上传文件总大小的可用空间
使用 curl
需要对命令行和 IBM Cloud® 有一定程度的熟悉,并从 服务凭证、端点参考 或 控制台 中获得必要的信息。
将文件分割为多个部分
对于多部分上传,每个文件部分(最后一部分除外)必须至少为 5 MB。 要将文件分割成不同部分,可以在终端窗口中运行 split。 当您决定如何分割文件时,请记住,多部分上传的最大部分数为10,000( 10k )。
在下面的示例中,split命令使用 -b 选项,值为 100M,文件名为 TESTFILE.iso,前缀为“part-”。
split -b 100M TESTFILE.iso part-
此命令生成指定大小的文件部分,文件名分别为part-aa、part-ab、part-ac,以此类推。
开始上传并获取 UploadID
要启动新的多部分上传,请运行 cURL,向带有查询参数 uploads
的对象发出 POST
请求,这将创建一个新的 UploadId
值。 请将正在上传的物品的每个部分与 UploadID
进行对照。
示例请求
curl -X "POST" "https://s3.private.us-south.cloud-object-storage.appdomain.cloud/mputest/TESTFILE.iso?uploads"
-H "Authorization: bearer $bearertoken"
示例响应
_<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<InitiateMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Bucket>mputest</Bucket>
<Key>TESTFILE.iso</Key>
<UploadId>01000194-8fab-0f08-3c54-d7df03b4a127</UploadId>
</InitiateMultipartUploadResult>_
从回复中记下 UploadID
。 在这个例子中,UploadID
的值为 01000194-8fab-0f08-3c54-d7df03b4a127
。
使用脚本上传零件并生成XML块
接下来,您运行 cURL,为要上传的每个文件部分发出 PUT
请求。 每个部分上传的响应头都包含一个ETag值,您必须将其保存为多部分上传操作最后一步的输入。
您可以使用如下bash脚本,而无需手动上传每个部分。 脚本有两个功能:
- 上传零件
- 创建XML零件清单,该清单保存在本地 /tmp 目录中
当每个文件部分上传时,脚本从响应头中提取其ETag并将其与零件编号一起保存到一个XML块中,作为最后一步的输入。
示例脚本
#!/usr/bin/env bash
set -euo pipefail
# ─── Configuration ───────────────────────────────────────────────────────────────
# Public endpoint for your bucket
ENDPOINT="$COS endpoint"
BUCKET="$bucket"
KEY="$Filename"
UPLOAD_ID="$uploadID gained from initiation of upload"
ACCESS_TOKEN="$BEARERTOKEN"
PARTS_PREFIX="part-"
MANIFEST="parts_manifest.xml"
# ─────────────────────────────────────────────────────────────────────────────────
# 1) Start a fresh manifest
cat > "$MANIFEST" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<CompleteMultipartUpload>
EOF
part=1
for f in ${PARTS_PREFIX}*; do
if [[ ! -r "$f" ]]; then
echo "ERROR: no files matching ${PARTS_PREFIX}*" >&2
exit 1
fi
echo "Uploading $f as part $part…"
# 2) PUT the part, capture headers
hdrfile=$(mktemp)
http_code=$(
curl -sS \
-D "$hdrfile" \
-o /dev/null \
-X PUT "${ENDPOINT}/${BUCKET}/${KEY}?partNumber=${part}&uploadId=${UPLOAD_ID}" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
--data-binary @"${f}" \
-w '%{http_code}'
)
if [[ "$http_code" != "200" ]]; then
echo "ERROR: HTTP $http_code for part $part" >&2
sed 's/^/ /' "$hdrfile" >&2
rm -f "$hdrfile"
exit 1
fi
# 3) Extract clean ETag (strip quotes/carriage returns)
etag=$(grep -i '^ETag:' "$hdrfile" \
| cut -d' ' -f2 \
| tr -d '"\r')
rm -f "$hdrfile"
if [[ -z "$etag" ]]; then
echo "ERROR: no ETag for part $part" >&2
exit 1
fi
echo " → Part $part ETag: $etag"
# 4) Append a well-formed <Part> block
printf ' <Part>\n <PartNumber>%d</PartNumber>\n <ETag>"%s"</ETag>\n </Part>\n' \
"$part" "$etag" >> "$MANIFEST"
part=$((part + 1))
done
# 5) Close the manifest
echo '</CompleteMultipartUpload>' >> "$MANIFEST"
echo "✔ Manifest generated: $MANIFEST"
## Complete multipart upload {: #curl-multipart-complete step}
When all parts are finished uploading, you complete the upload by sending a request with the `UploadId` and an XML block that lists each part number and its respective Etag value.
示例请求
curl -X POST "https://s3.private.us-south.cloud-object-storage.appdomain.cloud/mputest/TESTFILE.iso?uploadId=01000194-8fab-0f08-3c54-d7df03b4a127"
-H "Authorization: Bearer $bearertoken" -H "Content-Type: application/xml" --data-binary @parts_manifest.xml
示例响应
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<CompleteMultipartUploadResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Location>http://s3.private.us-south.cloud-object-storage.appdomain.cloud/mputest/TESTFILE.iso</Location>
<Bucket>mputest</Bucket>
<Key>TESTFILE.iso</Key>
<ETag>"1a90419141160aa6713b8d196773345e-94"</ETag>
</CompleteMultipartUploadResult>
后续步骤
如果一切顺利,您会收到文件已成功上传到想要的存储桶的确认信息。 如果遇到错误,请务必清理不完整的多部分上传。 如果未停止未完成的多部分上传,则部分上传会继续使用资源。 请参阅 使用 cURL 获取 语法,以获取或停止不完整的多部分上传。