OSS提供的分片上传(MultipartUpload)功能,将要上传的较大文件(Object)分成多个分片(Part)来分别上传,上传完成后再调用CompleteMultipartUpload接口将这些Part组合成一个Object来达到断点续传的效果。
注意事项
在分片上传之前,请确保您已了解该功能。更多信息,请参见分片上传。
当您使用webpack或browserify等打包工具时,请通过npm install ali-oss的方式安装Browser.js SDK。
通过浏览器访问OSS时涉及跨域请求,如果未设置跨域规则,浏览器会拒绝跨域访问请求。如果您希望通过浏览器可以正常访问OSS,需要通过OSS设置跨域规则。具体操作,请参见准备工作。
由于Browser.js SDK通常在浏览器环境下使用,为避免暴露阿里云账号访问密钥(AccessKey ID和AccessKey Secret),强烈建议您使用临时访问凭证的方式执行OSS相关操作。
临时访问凭证包括临时访问密钥(AccessKey ID和AccessKey Secret)和安全令牌(SecurityToken)。获取临时访问凭证的具体操作,请参见授权访问。
分片上传完整示例代码
当需要上传的文件大小较大时,您可以通过MultipartUpload接口进行分片上传。分片上传是指将要上传的文件分成多个数据块(Part)来分别上传。当其中一些分片上传失败后,OSS将保留上传进度记录,再次重传时只需要上传失败的分片,而不需要重新上传整个文件。
通常在文件大于100 MB的情况下,建议采用分片上传的方法,通过断点续传和重试,提高上传成功率。如果在文件小于100 MB的情况下使用分片上传,且partSize设置不合理的情况下,可能会出现无法完整显示上传进度的情况。对于小于100 MB的文件,建议使用简单上传的方式。
以下代码以分片上传的方式将文件上传至examplebucket下的exampleobject.txt文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<button id="submit">上传</button>
<input id="file" type="file" />
<!--导入sdk文件-->
<script
type="text/javascript"
src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
></script>
<script type="text/javascript">
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: "yourRegion",
authorizationV4: true,
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: "yourAccessKeyId",
accessKeySecret: "yourAccessKeySecret",
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: "yourSecurityToken",
// 填写Bucket名称,例如examplebucket。
bucket: "examplebucket",
});
const headers = {
// 指定该Object被下载时的网页缓存行为。
"Cache-Control": "no-cache",
// 指定该Object被下载时的名称。
"Content-Disposition": "example.txt",
// 指定该Object被下载时的内容编码格式。
"Content-Encoding": "utf-8",
// 指定过期时间,单位为毫秒。
Expires: "1000",
// 指定Object的存储类型。
"x-oss-storage-class": "Standard",
// 指定Object标签,可同时设置多个标签。
"x-oss-tagging": "Tag1=1&Tag2=2",
// 指定初始化分片上传时是否覆盖同名Object。此处设置为true,表示禁止覆盖同名Object。
"x-oss-forbid-overwrite": "true",
};
// 指定上传到examplebucket的Object名称,例如exampleobject.txt。
const name = "exampleobject.txt";
// 获取DOM。
const submit = document.getElementById("submit");
const options = {
// 获取分片上传进度、断点和返回值。
progress: (p, cpt, res) => {
console.log(p);
},
// 设置并发上传的分片数量。
parallel: 4,
// 设置分片大小。默认值为1 MB,最小值为100 KB。
partSize: 1024 * 1024,
// headers,
// 自定义元数据,通过HeadObject接口可以获取Object的元数据。
meta: { year: 2020, people: "test" },
mime: "text/plain",
};
// 监听按钮。
submit.addEventListener("click", async () => {
try {
const data = document.getElementById("file").files[0];
// 分片上传。
const res = await client.multipartUpload(name, data, {
...options,
// 设置上传回调。
// 如果不涉及回调服务器,请删除callback相关设置。
callback: {
// 设置回调请求的服务器地址。
url: "http://examplebucket.aliyuncs.com:23450",
// 设置回调请求消息头中Host的值,即您的服务器配置Host的值。
host: "yourHost",
/* eslint no-template-curly-in-string: [0] */
// 设置发起回调时请求body的值。
body: "bucket=${bucket}&object=${object}&var1=${x:var1}",
// 设置发起回调请求的Content-Type。
contentType: "application/x-www-form-urlencoded",
customValue: {
// 设置发起回调请求的自定义参数。
var1: "value1",
var2: "value2",
},
},
});
console.log(res);
} catch (err) {
console.log(err);
}
});
</script>
</body>
</html>
在使用MultipartUpload接口时,如果遇到ConnectionTimeoutError
超时问题,业务方需自行处理超时逻辑。例如通过缩小分片大小、增加超时时间、重试请求或者捕获ConnectionTimeoutError
错误等方法处理超时。更多信息,请参见网络错误处理。
取消分片上传事件
您可以调用client.abortMultipartUpload
方法来取消分片上传事件。当一个分片上传事件被取消后,无法再使用该uploadId进行任何操作,已上传的分片数据会被删除。
以下代码用于取消分片上传事件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<button id="submit">上传</button>
<button id="abort">中断</button>
<!--导入sdk文件-->
<script
type="text/javascript"
src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
></script>
<script type="text/javascript">
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: "yourRegion",
authorizationV4: true,
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: "yourAccessKeyId",
accessKeySecret: "yourAccessKeySecret",
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: "yourSecurityToken",
// 填写Bucket名称,例如examplebucket。
bucket: "examplebucket",
});
// 生成用于分片上传的100 MB大小的文件。
const fileContent = Array(1024 * 1024 * 100)
.fill("a")
.join("");
const file = new File([fileContent], "multipart-upload-file");
// 设置上传到examplebucket的Object名称,例如exampleobject.txt。
const name = "exampleobject.txt";
// 设置中断点。
let abortCheckpoint;
// 获取DOM。
const submit = document.getElementById("submit");
const abort = document.getElementById("abort");
// 监听上传按钮,单击“上传”后开始分片上传。
submit.addEventListener("click", async () => {
try {
const res = await client.multipartUpload(name, file, {
progress: (p, cpt, res) => {
// 为中断点赋值。
abortCheckpoint = cpt;
// 获取上传进度。
console.log(p);
},
});
} catch (err) {
console.log(err);
}
});
// 监听中断按钮。
abort.addEventListener("click", () => {
// 中断分片上传。
client.abortMultipartUpload(
abortCheckpoint.name,
abortCheckpoint.uploadId
);
});
</script>
</body>
</html>
列举已上传的分片
调用client.listParts
方法列举出指定uploadId下所有已经上传成功的分片。
以下代码用于列举已上传的分片:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<button id="submit">上传</button>
<button id="check">列举已上传的分片</button>
<!--导入sdk文件-->
<script
type="text/javascript"
src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
></script>
<script type="text/javascript">
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'yourRegion',
authorizationV4: true,
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret',
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: 'yourSecurityToken',
// 填写Bucket名称,例如examplebucket。
bucket: "examplebucket",
});
// 生成用于分片上传的100 MB大小的文件。
const fileContent = Array(1024 * 1024 * 100)
.fill("a")
.join("");
const file = new File([fileContent], "multipart-upload-file");
// 设置上传到examplebucket的Object名称,例如exampleobject.txt。
const name = "exampleobject.txt";
// 设置中断点。
let abortCheckpoint;
// 获取DOM。
const submit = document.getElementById("submit");
const check = document.getElementById("check");
// 监听按钮。
submit.addEventListener("click", async () => {
try {
const res = await client.multipartUpload(name, file, {
progress: (p, cpt, res) => {
// 为中断点赋值。
abortCheckpoint = cpt;
// 获取上传进度。
console.log("progress=====", p);
},
});
} catch (err) {
console.log(err);
}
});
// 监听按钮。
check.addEventListener("click", async () => {
// 列举已上传的分片。
const result = await client.listParts(name, abortCheckpoint.uploadId);
console.log(result);
});
</script>
</body>
</html>
列举分片上传事件
调用client.listUploads
方法列举出所有执行中的分片上传事件,即已初始化但尚未完成或已取消的分片上传事件。
以下代码用于列举分片上传事件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
</head>
<body>
<button id="check">列举分片上传事件</button>
<!--导入sdk文件-->
<script
type="text/javascript"
src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"
></script>
<script type="text/javascript">
const client = new OSS({
// yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'yourRegion',
authorizationV4: true,
// 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
accessKeyId: 'yourAccessKeyId',
accessKeySecret: 'yourAccessKeySecret',
// 从STS服务获取的安全令牌(SecurityToken)。
stsToken: 'yourSecurityToken',
// 填写Bucket名称,例如examplebucket。
bucket: "examplebucket",
});
// 获取DOM。
const check = document.getElementById("check");
// 监听按钮。
check.addEventListener("click", async () => {
// 获取所有已初始化但尚未完成或已取消的分片上传事件。
const result = await client.listUploads({ "max-uploads": 100 });
console.log("uploads", result.uploads);
});
</script>
</body>
</html>
相关文档
关于分片上传的完整示例代码,请参见GitHub示例。
Browser.js SDK分片上传调用的方法
multipartUpload
中封装了三个API接口,详情如下:关于初始化分片上传事件的API接口说明,请参见InitiateMultipartUpload。
关于分片上传Part的API接口说明,请参见UploadPart。
关于完成分片上传的API接口说明,请参见CompleteMultipartUpload。
关于取消分片上传事件的API接口说明,请参见AbortMultipartUpload。
关于列举已上传分片的API接口说明,请参见ListParts。
关于列举所有执行中的分片上传事件(即已初始化但尚未完成或已取消的分片上传事件)的API接口说明,请参见ListMultipartUploads。
常见问题
报错PLease set the etag of expose-headers in Oss.如何处理?
问题原因
未正确设置跨域。
解决方法
您需要为当前Bucket设置跨域。设置跨域规则时需要暴露常见Header(x-oss-request-id和ETag)。具体步骤,请参见跨域设置。
报错The operation is not supported for this resource.如何处理?
问题原因
您在调用CompleteMultipartUpload接口时设置了Object存储类型。
解决方法
不支持在分片上传过程中调用CompleteMultipartUpload时设置Object存储类型。如果您需要在分片上传过程中指定Object存储类型,您需要在调用InitiateMultipartUpload时进行设置。