OSS提供的分片上传(Multipart Upload)功能,将要上传的较大文件(Object)分成多个分片(Part)来分别上传,上传完成后再调用CompleteMultipartUpload接口将这些Part组合成一个Object来达到断点续传的效果。
背景信息
当需要上传的文件较大时,您可以通过MultipartUpload
方法进行分片上传。分片上传是指将要上传的文件分成多个数据块(Part)来分别上传。当其中一些分片上传失败后,OSS将保留上传进度记录。当您再次重传时,只需要上传失败的分片,不需要重新上传整个文件。
通常在文件大于100 MB的情况下,建议采用分片上传的方法,通过断点续传和重试,提高上传成功率。如果在文件小于100 MB的情况下使用分片上传,且partSize设置不合理的情况下,可能会出现无法完整显示上传进度的情况。对于小于100 MB的文件,建议使用简单上传的方式。
在使用MultipartUpload
方法时,如果遇到ConnectionTimeoutError
超时问题,业务方需自行处理超时逻辑。例如通过缩小分片大小、增加超时时间、重试请求或者捕获ConnectionTimeoutError
错误等方法处理超时。更多信息,请参见网络错误处理。
分片上传涉及的相关参数说明请参见下表。
类型 | 参数 | 说明 |
必选参数 | name {String} | Object完整路径,Object完整路径中不能包含Bucket名称。 |
file {String|File} | 表示文件路径或者HTML5文件。 | |
[options] {Object} 可选参数 | [checkpoint] {Object} | 记录本地分片上传结果的文件。开启断点续传功能时需要设置此参数,上传过程中的进度信息会保存在该文件中,如果某一分片上传失败,再次上传时会根据文件中记录的点继续上传。上传完成后,该文件会被删除。 |
[parallel] {Number} | 并发上传的分片个数,默认值为5。如果无特殊需求,无需手动设置此参数。 | |
[partSize] {Number} | 指定上传的每个分片的大小,范围为100 KB~5 GB。单个分片默认大小为1 * 1024 * 1024(即1 MB)。如果无特殊需求,无需手动设置此参数。 | |
[progress] {Function} | 表示进度回调函数,用于获取上传进度,可以是async的函数形式。回调函数包含三个参数:
| |
[meta] {Object} | 用户自定义的Header meta信息,Header前缀为 | |
[mime] {String} | 设置Content-Type请求头。 | |
[headers] {Object} | 其他Header。更多信息,请参见RFC 2616。其中:
|
分片上传完整示例
Node.js分片上传过程中不支持MD5校验。建议分片上传完成后调用CRC64库自行判断是否进行CRC64校验。
以下代码通过multipartUpload
方法进行分片上传。
const OSS = require('ali-oss');
const path = require("path");
const client = new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'yourregion',
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填写存储空间名称。
bucket: 'yourbucketname',
});
const progress = (p, _checkpoint) => {
// Object的上传进度。
console.log(p);
// 分片上传的断点信息。
console.log(_checkpoint);
};
const headers = {
// 指定Object的存储类型。
'x-oss-storage-class': 'Standard',
// 指定Object标签,可同时设置多个标签。
'x-oss-tagging': 'Tag1=1&Tag2=2',
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
'x-oss-forbid-overwrite': 'true'
}
// 开始分片上传。
async function multipartUpload() {
try {
// 依次填写Object完整路径(例如exampledir/exampleobject.txt)和本地文件的完整路径(例如D:\\localpath\\examplefile.txt)。Object完整路径中不能包含Bucket名称。
// 如果本地文件的完整路径中未指定本地路径(例如examplefile.txt),则默认从示例程序所属项目对应本地路径中上传文件。
const result = await client.multipartUpload('exampledir/exampleobject.txt', path.normalize('D:\\localpath\\examplefile.txt'), {
progress,
// headers,
// 指定meta参数,自定义Object的元数据。通过head接口可以获取到Object的meta数据。
meta: {
year: 2020,
people: 'test',
},
});
console.log(result);
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
const head = await client.head('exampledir/exampleobject.txt');
console.log(head);
} catch (e) {
// 捕获超时异常。
if (e.code === 'ConnectionTimeoutError') {
console.log('TimeoutError');
// do ConnectionTimeoutError operation
}
console.log(e);
}
}
multipartUpload();
以上分片上传完整示例调用的方法multipartUpload
中封装了初始化分片上传、上传分片以及完成分片上传三个API接口。如果您希望分步骤实现分片上传,请依次调用.initMultipartUpload、.uploadPart以及.completeMultipartUpload方法。
取消分片上传事件
您可以调用client.abortMultipartUpload
方法来取消分片上传事件。当一个分片上传事件被取消后,无法再使用该uploadId做任何操作,已经上传的分片数据会被删除。
以下代码用于取消分片上传事件。
const OSS = require("ali-oss");
const client = new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: "yourregion",
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填写存储空间名称。
bucket: "yourbucketname",
});
async function abortMultipartUpload() {
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
const name = "exampledir/exampleobject.txt";
// 填写uploadId。uploadId来源于调用InitiateMultipartUpload完成初始化分片之后的返回结果。
const uploadId = "0004B999EF518A1FE585B0C9360D****";
const result = await client.abortMultipartUpload(name, uploadId);
console.log(result);
}
abortMultipartUpload();
列举分片上传事件
调用client.listUploads
方法列举出所有执行中的分片上传事件,即已初始化但尚未完成或尚未取消的分片上传事件。
const OSS = require("ali-oss");
const client = new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: "yourregion",
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填写存储空间名称。
bucket: "yourbucketname",
});
async function listUploads(query = {}) {
// query中支持设置prefix、marker、delimiter、upload-id-marker和max-uploads参数。
const result = await client.listUploads(query);
result.uploads.forEach((upload) => {
// 分片上传的uploadId。
console.log(upload.uploadId);
// 将所有上传完成后的分片(Part)组合为一个完整的Object,并指定Object完整路径。
console.log(upload.name);
});
}
const query = {
// 指定此次返回Multipart Uploads事件的最大个数。max-uploads参数的默认值和最大值均为1000。
"max-uploads": 1000,
};
listUploads(query);
列举已上传的分片
分片上传过程中,调用client.listParts
方法列举指定uploadId下所有已经上传成功的分片。
const OSS = require("ali-oss");
const client = new OSS({
// yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: "yourregion",
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
authorizationV4: true,
// 填写存储空间名称。
bucket: "yourbucketname",
});
async function listParts() {
const query = {
// 指定此次返回的最大分片(Part)个数。max-parts参数的默认值和最大值均为1000。
"max-parts": 1000,
};
let result;
do {
result = await client.listParts(
// 填写Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
"exampledir/exampleobject.txt",
// uploadId来源于调用InitiateMultipartUpload完成初始化分片之后,且在调用CompleteMultipartUpload完成分片上传之前的返回结果
"0004B999EF518A1FE585B0C9360D****",
query
);
// 指定下次列举分片的起始位置,只有分片号大于此参数值的分片会被列举。
query["part-number-marker"] = result.nextPartNumberMarker;
result.parts.forEach((part) => {
console.log(part.PartNumber);
console.log(part.LastModified);
console.log(part.ETag);
console.log(part.Size);
});
} while (result.isTruncated === "true");
}
listParts();
相关文档
关于分片上传的完整示例代码,请参见GitHub示例。
Node.js SDK分片上传调用的方法
multipartUpload
中封装了三个API接口,详情如下:关于初始化分片上传事件的API接口说明,请参见InitiateMultipartUpload。
关于分片上传Part的API接口说明,请参见UploadPart。
关于完成分片上传的API接口说明,请参见CompleteMultipartUpload。
关于取消分片上传事件的API接口说明,请参见AbortMultipartUpload。
关于列举已上传分片的API接口说明,请参见ListParts。
关于列举所有执行中的分片上传事件(即已初始化但尚未完成或尚未取消的分片上传事件)的API接口说明,请参见ListMultipartUploads。