本文介绍如何将源Bucket中的文件(Object)复制到同一地域下相同或不同目标Bucket中。

注意事项

  • 拷贝文件时,您必须拥有源文件的读权限及目标Bucket的读写权限。
  • 拷贝文件时,您需要确保源Bucket和目标Bucket均未设置合规保留策略,否则报错The object you specified is immutable.
  • 不支持跨地域拷贝。例如不能将华东1(杭州)地域存储空间中的文件拷贝到华北1(青岛)地域。

拷贝小文件

您可以通过copy方法在同一个Bucket或者同一个Region下的不同Bucket之间拷贝文件,文件大小不能超过1 GB。

  • 同一个Bucket中拷贝文件

    以下代码用于在同一个Bucket中拷贝文件。

    const OSS = require('ali-oss');
    const client = new OSS({
    
      // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
      region: 'yourRegion',
      // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
      accessKeyId: 'yourAccessKeyId',
      accessKeySecret: 'yourAccessKeySecret',
      // 填写Bucket名称。例如examplebucket。
      bucket: 'examplebucket',
      // 设置是否启用HTTPS。设置secure为true时,表示启用。
      // secure: true
    })
    // 拷贝同一个Bucket中的文件。
    // 填写拷贝后和拷贝前的文件完整路径。文件完整路径中不能包含Bucket名称。
    client.copy('destexampleobject.txt', 'srcexampleobject.txt',
    // 设置目标文件的HTTP头和自定义目标文件的元信息。
    //{
        // 指定headers参数,设置目标文件的HTTP头。如果未指定headers参数,则目标文件与源文件的HTTP头相同,即拷贝源文件的HTTP头。
        // headers:{
            //'Cache-Control': 'no-cache',        
            // 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作,并返回200 OK。
            //'if-match': '5B3C1A2E053D763E1B002CC607C5****',
            // 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作,并返回200 OK。
            //'if-none-match': '5B3C1A2E053D763E1B002CC607C5****', 
            // 如果指定的时间早于文件实际修改时间,则执行拷贝操作,并返回200 OK。
            //'if-modified-since': '2021-12-09T07:01:56.000Z', 
            // 如果指定的时间晚于文件实际修改时间,则执行拷贝操作,并返回200 OK。
            //'if-unmodified-since': '2021-12-09T07:01:56.000Z', 
            // 指定OSS创建目标Object时的访问权限,此处设置为private,表示只有Object的拥有者和授权用户有该Object的读写权限,其他用户没有权限操作该Object。
            //'x-oss-object-acl': 'private', 
            // 指定Object的对象标签,可同时设置多个标签。
            //'x-oss-tagging': 'Tag1=1&Tag2=2',
            // 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
            //'x-oss-forbid-overwrite': 'true', 
        //},
        // 指定meta参数,自定义目标文件的元信息。如果未指定meta参数,目标文件与源文件的元信息相同,即拷贝源文件的元信息。
        //meta:{
            // location: 'hangzhou',
            // year: 2015,
            // people: 'mary'
        //}
    //}
    ).then((res) => {
        console.log(res);
    }).catch(e => {
      console.log(e);
    })
  • 同一Region下不同Bucket之间拷贝文件

    以下代码用于在同一个Region下不同Bucket之间拷贝文件。

    const OSS = require('ali-oss');
    const client = new OSS({
    
      // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
      region: 'yourRegion',
      // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
      accessKeyId: 'yourAccessKeyId',
      accessKeySecret: 'yourAccessKeySecret',
      // 填写目标Bucket名称。
      bucket: 'destexamplebucket',
    });
    // 分别填写拷贝后的文件名称destobject.txt、拷贝前的文件名称srcobject.txt以及拷贝前文件所属的Bucket名称。
    client.copy('destobject.txt', 'srcobject.txt', 'srcbucket', {
        // 指定headers参数,设置目标文件的HTTP头。如果未指定headers参数,则目标文件与源文件的HTTP头相同,即拷贝源文件的HTTP头。
        // headers:{
        // 'Cache-Control': 'no-cache',
        //},
        // 指定meta参数,自定义目标文件的元信息。如果未指定meta参数,目标文件与源文件的元信息相同,即拷贝源文件的元信息。
        // meta:{
        // location: 'hangzhou',
        // year: 2015,
        // people: 'mary'
        //}
      })
      .then(r => console.log(r));

拷贝大文件

对于大于1 GB文件,您可以使用multipartUploadCopy方法进行分片拷贝。

以下代码用于在同一个Region下不同Bucket之间拷贝文件。

const OSS = require('ali-oss');
const store = new OSS({
  // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourRegion',
  // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  // 填写目标Bucket名称。
  bucket: 'destexamplebucket',
});

const copyheaders = {
  // 如果源Object的ETag值和用户提供的ETag相等,则执行拷贝操作;否则返回412 HTTP错误码(预处理失败)。
  'x-oss-copy-source-if-match': '5B3C1A2E053D763E1B002CC607C5****',
  // 如果传入的ETag值和Object的ETag不匹配,则执行拷贝操作,并返回200 OK;否则返回304 Not Modified。
  'x-oss-copy-source-if-none-match': '5B3C1A2E053D763E1B002CC607C5****', 
  // 如果参数传入的时间等于或者晚于文件实际修改时间,则执行拷贝操作,并返回200 OK;否则返回412 precondition failed错误。
  'x-oss-copy-source-if-unmodified-since': '2022-12-09T07:01:56.000Z',
  // 如果指定的时间早于实际修改时间,则执行拷贝操作,并返回200 OK;否则返回304 not modified。
  'x-oss-copy-source-if-modified-since': '2022-12-09T07:01:56.000Z' 
}
const headers = {
  // 指定该Object被下载时的网页的缓存行为。
  'Cache-Control': 'no-cache',
  // 指定该Object被下载时的名称。
  'Content-Disposition': 'somename', 
  // 指定该Object被下载时的内容编码格式。
  'Content-Encoding': 'utf-8',
  // 指定过期时间,单位为毫秒。
  'Expires': '1000'
}

let savedCpt;

// 填写拷贝后的文件完整路径,文件完整路径中不能包含Bucket名称,例如destexampleobject.txt。
store.multipartUploadCopy('destexampleobject.txt'
, { 
  // 填写拷贝前的文件完整路径,文件完整路径中不能包含Bucket名称,例如srcexampleobject.txt。
  sourceKey: 'srcexampleobject.txt',
  // 填写源Bucket名称,例如sourcebucket。
  sourceBucketName: 'sourcebucket'
}).then(r=>console.log(r)).catch(e=>console.log(e))

// 填写拷贝后的文件完整路径,文件完整路径中不能包含Bucket名称,例如destexampleobject.txt。
store.multipartUploadCopy('destexampleobject.txt'
, { 
  // 填写拷贝前的文件完整路径,文件完整路径中不能包含Bucket名称,例如srcexampleobject.txt。
  sourceKey: 'srcexampleobject.txt',
  // 填写源Bucket名称,例如sourcebucket。
  sourceBucketName: 'sourcebucket'
});
  // 设置并行上传的分片数量。
  parallel: 4, 
  // 设置分片大小。
  partSize: 1024 * 1024,
  progress: function (p, cpt, res) {
    console.log(p);
    savedCpt = cpt;
    console.log(cpt);
    console.log(res.headers['x-oss-request-id']);
  }, 
  //headers, 
  //copyheaders, 
}).then(r=>console.log(r)).catch(e=>console.log(e))


// 填写拷贝后的文件完整路径,文件完整路径中不能包含Bucket名称,例如destexampleobject.txt。
store.multipartUploadCopy('destexampleobject.txt'
, { 
  // 填写拷贝前的文件完整路径,文件完整路径中不能包含Bucket名称,例如srcexampleobject.txt。
  sourceKey: 'srcexampleobject.txt',
  // 填写源Bucket名称,例如sourcebucket。
  sourceBucketName: 'sourcebucket'
});
  checkpoint: savedCpt,
  progress: function (p, cpt, res) {
    console.log(p);
    console.log(cpt);
    console.log(res.headers['x-oss-request-id']);
  }
});

相关文档

  • 拷贝小文件
    • 关于拷贝小文件的完整示例代码,请参见GitHub示例
    • 关于拷贝小文件的API接口说明,请参见CopyObject
  • 拷贝大文件
    • 关于拷贝大文件的完整示例代码,请参见GitHub示例
    • 关于拷贝大文件的API接口说明,请参见UploadPartCopy