You need to enable JavaScript to run this app.
导航
追加上传(Node.js SDK)
最近更新时间:2024.02.26 17:05:19首次发布时间:2022.05.13 18:28:15

appendObject 接口用于追加写对象。追加写是指在已上传的对象末尾追加内容。只能对类型为 Appendable 的对象使用此接口。通过直接上传和分片上传创建的对象类型为 Normal。

注意事项

  • 追加上传对象前,您必须具有 tos:PutObject 权限,具体操作请参见权限配置指南
  • 上传对象时,对象名必须满足一定规范,详细信息请参见对象命名规范
  • TOS 是面向海量存储设计的分布式对象存储产品,内部分区存储了对象索引数据,为横向扩展您上传对象和下载对象时的最大吞吐量,和减小热点分区的概率,请您避免使用字典序递增的对象命名方式,详细信息,请参见性能优化
  • 如果桶中已经存在同名对象,则新对象会覆盖已有的对象。桶开启多版本的场景下,则会保留原有对象,生成一个新版本号用于标识新上传的对象。
  • 追加上传对象不支持 Chunk-Encoded 的请求方式,当您追加上传网络流时请迭代获取数据再追加上传。

限制说明

使用 appendObject 接口时,对象的大小限制说明如下:

  • 追加后的对象大小不能大于 5GiB。
  • 通过 appendObject 创建的对象,进行 putObject 操作,对象被覆盖且对象类型由 Appendable 变为 Normal。反之通过 putObject 上传的对象不支持追加写操作。
  • appendObject 创建的对象不支持拷贝。
  • 如果对象类型为低频存储或归档闪回存储,则无法使用 appendObject 接口。
  • 如果您的存储桶处于开启或暂停多版本控制功能的状态下,则无法使用 appendObject 接口。

示例代码

追加上传

以下代码用于将字符流追加上传到目标桶。

// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
import https from 'https';

// 创建客户端
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", // 填写域名地址
});

async function main() {
  try {
    const bucketName = 'node-sdk-test-bucket';
    const objectName = 'append-example.txt';

    // 第一次追加
    const appendResult = await client.appendObject({
      bucket: bucketName,
      key: objectName,
      offset: 0,
      body: Buffer.from('your append object value.'),
    });
    console.log('appendResult', appendResult);

    // 追加上传网络流
    const req = https.get('https://www.volcengine.com/');
    const res = await new Promise((resolve) => req.on('response', resolve));
    await client.appendObject({
      bucket: bucketName,
      key: objectName,
      offset: appendResult.data.nextAppendOffset,
      body: res,
      contentLength: +res.headers['content-length'],
    });

    // 查询对象的大小
    const { data } = await client.headObject({
      bucket: bucketName,
      key: objectName,
    });
    // object size:
    console.log('object size:', data['content-length']);
  } catch (error) {
    handleError(error);
  }
}

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);
  }
}

main();

配置进度条

追加上传时可通过 dataTransferStatusChange 参数接受上传进度,代码示例如下。

// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { DataTransferType, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
import https from 'https';

// 创建客户端
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", // 填写域名地址
});

async function main() {
  try {
    const bucketName = 'node-sdk-test-bucket';
    const objectName = 'append-example.txt';
    const rateLimit1M = 1024 * 1024;

    // 第一次追加
    const appendResult = await client.appendObject({
      bucket: bucketName,
      key: objectName,
      offset: 0,
      body: Buffer.from('your append object value.'),
    });
    console.log('appendResult', appendResult);

    // 追加上传网络流
    const req = https.get('https://www.volcengine.com/');
    const res = await new Promise((resolve) => req.on('response', resolve));
    await client.appendObject({
      bucket: bucketName,
      key: objectName,
      offset: appendResult.data.nextAppendOffset,
      body: res,
      contentLength: +res.headers['content-length'],
      // 通过自定义方式设置回调函数查看上传进度
      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');
        }
      },
    });

    // 查询对象的大小
    const { data } = await client.headObject({
      bucket: bucketName,
      key: objectName,
    });
    // object size:
    console.log('object size:', data['content-length']);
  } catch (error) {
    handleError(error);
  }
}

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);
  }
}

main();

配置客户端限速

追加上传时可以通过客户端使用 rateLimiter 参数对上传数据所占用的带宽进行限制,代码如下所示。

// 导入 SDK, 当 TOS Node.JS SDK 版本小于 2.5.2 请把下方 TosClient 改成 TOS 导入
import { DataTransferType, createDefaultRateLimiter, TosClient, TosClientError, TosServerError } from '@volcengine/tos-sdk';
import https from 'https';

// 创建客户端
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", // 填写域名地址
});

async function main() {
  try {
    const bucketName = 'node-sdk-test-bucket';
    const objectName = 'append-example.txt';
    const rateLimit1M = 1024 * 1024;

    // 第一次追加
    const appendResult = await client.appendObject({
      bucket: bucketName,
      key: objectName,
      offset: 0,
      body: Buffer.from('your append object value.'),
    });
    console.log('appendResult', appendResult);

    // 追加上传网络流
    const req = https.get('https://www.volcengine.com/');
    const res = await new Promise((resolve) => req.on('response', resolve));
    await client.appendObject({
      bucket: bucketName,
      key: objectName,
      offset: appendResult.data.nextAppendOffset,
      body: res,
      contentLength: +res.headers['content-length'],
      // 通过自定义方式设置回调函数查看上传进度
      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');
        }
      },
      // 上传对象并在客户端限制上传速度为 1M/s
      rateLimiter: createDefaultRateLimiter(rateLimit1M, rateLimit1M),
    });

    // 查询对象的大小
    const { data } = await client.headObject({
      bucket: bucketName,
      key: objectName,
    });
    // object size:
    console.log('object size:', data['content-length']);
  } catch (error) {
    handleError(error);
  }
}

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);
  }
}

main();

相关文档

关于追加上传的 API 文档,请参见 AppendObject