使用断点续传上传的方式将文件上传到 TOS 时,您可以设置分片大小、上传分片的并发数、上传时客户端限速、事件回调函数等。上传过程中,如果出现网络异常或程序崩溃导致文件上传失败时,将从断点记录处继续上传未上传完成的部分。在上传的过程中可以通过调用传入的 cancelToken 中的 Cancel 方法取消对象上传。
tos:PutObject 权限,具体操作,请参见权限配置指南。Checkpoint 文件中,所以程序需要对 Checkpoint 文件有写权限。Checkpoint 文件中,如果上传过程中某一分片上传失败,再次上传时会 Checkpoint 文件中记录的点继续上传。上传完成后, Checkpoint 文件会被删除。
以下代码用于断点续传的方式上传文件。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
// 创建客户端
const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。
endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error) {
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} else if (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main() {
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/multipartExample';
// 本地 example_dir 文件夹下的 multipartExample 文件
const filePath = './example_dir/multipartExample';
const { data } = await client.uploadFile({
bucket: bucketName,
key: objectName,
// 上传的文件路径
file: filePath,
// 上传时指定分片大小
partSize: 5 * 1024 * 1024,
// 分片上传任务并发数量
taskNum: 5,
});
console.log('uploadFile result', data);
} catch (error) {
handleError(error);
}
}
main();
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
import fsp from 'fs/promises';
import path from 'path';
// 创建客户端
const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。
endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error) {
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} else if (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main() {
try {
const bucketName = 'node-sdk-test-bucket';
// 上传后的对象所在目录
const objectDirName = 'example_dir/';
// 上传本地 example_dir 文件夹下所有文件
const localDirPath = './example_dir/';
const localDirAbsolutePath = path.resolve(localDirPath) + '/';
async function walkDir(dirPath) {
for (const dirent of await fsp.readdir(dirPath, { withFileTypes: true })) {
const filePath = path.resolve(dirPath, dirent.name);
if (dirent.isDirectory()) {
walkDir(filePath);
continue;
}
const { data } = await client.uploadFile({
bucket: bucketName,
key: objectDirName + filePath.slice(localDirAbsolutePath.length),
// 上传的文件路径
file: filePath,
// 上传时指定分片大小
partSize: 5 * 1024 * 1024,
// 分片上传任务并发数量
taskNum: 5,
});
console.log(`uploadFile ${filePath} result: `, data);
}
}
await walkDir(localDirPath);
} catch (error) {
handleError(error);
}
}
main();
断点续传上传时可通过 dataTransferStatusChange 参数接收上传进度,代码示例如下。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { DataTransferType, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
// 创建客户端
const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。
endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error) {
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} else if (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main() {
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/multipartExample';
// 本地 example_dir 文件夹下的 multipartExample 文件
const filePath = './example_dir/multipartExample';
const { data } = await client.uploadFile({
bucket: bucketName,
key: objectName,
// 上传的文件路径
file: filePath,
// 上传时指定分片大小
partSize: 5 * 1024 * 1024,
// 分片上传任务并发数量
taskNum: 5,
// 通过自定义方式设置回调函数查看上传进度
dataTransferStatusChange: (event) => {
if (event.type === DataTransferType.Started) {
console.log('Data Transfer Started');
} else if (event.type === DataTransferType.Rw) {
const percent = ((event.consumedBytes / event.totalBytes) * 100).toFixed(2);
console.log(`Once Read:${event.rwOnceBytes},ConsumerBytes/TotalBytes: ${event.consumedBytes}/${event.totalBytes},${percent}%`);
} else if (event.type === DataTransferType.Succeed) {
const percent = ((event.consumedBytes / event.totalBytes) * 100).toFixed(2);
console.log(`Data Transfer Succeed, ConsumerBytes/TotalBytes:${event.consumedBytes}/${event.totalBytes},${percent}%`);
} else if (event.type === DataTransferType.Failed) {
console.log('Data Transfer Failed');
}
},
});
console.log('uploadFile result', data);
} catch (error) {
handleError(error);
}
}
main();
以下代码用于自定义断点续传上传回调函数。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { UploadEventType, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
// 创建客户端
const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。
endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error) {
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} else if (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main() {
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/multipartExample';
// 本地 example_dir 文件夹下的 multipartExample 文件
const filePath = './example_dir/multipartExample';
const { data } = await client.uploadFile({
bucket: bucketName,
key: objectName,
// 上传的文件路径
file: filePath,
// 上传时指定分片大小
partSize: 5 * 1024 * 1024,
// 分片上传任务并发数量
taskNum: 5,
// 事件监听回调
uploadEventChange: (event) => {
switch (event.type) {
case UploadEventType.createMultipartUploadSucceed: {
console.log(`Upload to ${event.bucket} ${event.key} create multipart upload success, upload id:${event.uploadId}`);
break;
}
case UploadEventType.createMultipartUploadFailed: {
console.log(`Upload to ${event.bucket} ${event.key} create multipart upload fail, upload id:${event.uploadId}`);
break;
}
case UploadEventType.uploadPartSucceed: {
console.log(`Upload to${event.bucket} ${event.key} part success, UploadPartInfo:%o`, event.uploadPartInfo);
break;
}
case UploadEventType.uploadPartAborted: {
console.log(`Upload to ${event.bucket} ${event.key} part aborted, upload id:${event.uploadId}`);
break;
}
case UploadEventType.uploadPartFailed: {
console.log(`Upload to ${event.bucket} ${event.key} part fail, upload id:${event.uploadId}`);
break;
}
case UploadEventType.completeMultipartUploadSucceed: {
console.log(`Upload to ${event.bucket} ${event.key} success, upload id:${event.uploadId}`);
break;
}
case UploadEventType.completeMultipartUploadFailed: {
console.log(`Upload to ${event.bucket} ${event.key} fail, upload id:${event.uploadId}, err: %o`, event.err);
break;
}
}
},
});
console.log('uploadFile result', data);
} catch (error) {
handleError(error);
}
}
main();
断点续传上传时可以通过客户端使用 tos.RateLimiter 接口对所占用的带宽进行限制,代码如下所示。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { createDefaultRateLimiter, DataTransferType, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
// 创建客户端
const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。
endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error) {
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} else if (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main() {
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/multipartExample';
// 本地 example_dir 文件夹下的 multipartExample 文件
const filePath = './example_dir/multipartExample';
const rateLimit1M = 1024;
const { data } = await client.uploadFile({
bucket: bucketName,
key: objectName,
// 上传的文件路径
file: filePath,
// 上传时指定分片大小
partSize: 5 * 1024 * 1024,
// 分片上传任务并发数量
taskNum: 5,
// 上传对象并在客户端限制上传速度为 1M/s
rateLimiter: createDefaultRateLimiter(rateLimit1M, rateLimit1M),
// 通过自定义方式设置回调函数查看上传进度
dataTransferStatusChange: (event) => {
if (event.type === DataTransferType.Started) {
console.log('Data Transfer Started');
} else if (event.type === DataTransferType.Rw) {
const percent = ((event.consumedBytes / event.totalBytes) * 100).toFixed(2);
console.log(`Once Read:${event.rwOnceBytes},ConsumerBytes/TotalBytes: ${event.consumedBytes}/${event.totalBytes},${percent}%`);
} else if (event.type === DataTransferType.Succeed) {
const percent = ((event.consumedBytes / event.totalBytes) * 100).toFixed(2);
console.log(`Data Transfer Succeed, ConsumerBytes/TotalBytes:${event.consumedBytes}/${event.totalBytes},${percent}%`);
} else if (event.type === DataTransferType.Failed) {
console.log('Data Transfer Failed');
}
},
});
console.log('uploadFile result', data);
} catch (error) {
handleError(error);
}
}
main();
以下代码用于在运行时取消正在执行的断点续传上传任务。
// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { CancelToken, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
// 创建客户端
const client = new TosClient({
accessKeyId: process.env['TOS_ACCESS_KEY'],
accessKeySecret: process.env['TOS_SECRET_KEY'],
region: "Provide your region", // 填写 Bucket 所在地域。以华北2(北京)为例,则 "Provide your region" 填写为 cn-beijing。
endpoint: "Provide your endpoint", // 填写域名地址
});
function handleError(error) {
if (error instanceof TosClientError) {
console.log('Client Err Msg:', error.message);
console.log('Client Err Stack:', error.stack);
} else if (error instanceof TosServerError) {
console.log('Request ID:', error.requestId);
console.log('Response Status Code:', error.statusCode);
console.log('Response Header:', error.headers);
console.log('Response Err Code:', error.code);
console.log('Response Err Msg:', error.message);
} else {
console.log('unexpected exception, message: ', error);
}
}
async function main() {
try {
const bucketName = 'node-sdk-test-bucket';
const objectName = 'example_dir/multipartExample';
// 本地 example_dir 文件夹下的 multipartExample 文件
const filePath = './example_dir/multipartExample';
// 生成 cancelTokenSource
const cancelTokenSource = CancelToken.source();
client.uploadFile({
bucket: bucketName,
key: objectName,
// 上传的文件路径
file: filePath,
// 上传时指定分片大小
partSize: 5 * 1024 * 1024,
// 注入 cancelToken
cancelToken: cancelTokenSource.token,
});
// 1秒后取消任务
setTimeout(() => {
cancelTokenSource.cancel();
console.log('cancel request');
}, 1000);
} catch (error) {
handleError(error);
}
}
main();