拷贝文件(Object)是指在不改变文件内容的情况下,将同一地域下的源存储空间(Bucket)内的文件复制到目标Bucket。

使用限制

  • 不支持跨地域拷贝Object。例如,不支持将华东1(杭州)地域下Bucke内的Object拷贝到华东2(上海)地域下的Bucket。
  • 不支持对通过追加上传方式生成的Object进行拷贝。

注意事项

  • 您需要有源Object的读权限及目标Bucket的读写权限,否则无法完成拷贝操作。
  • 拷贝文件时,您需要确保源Bucket和目标Bucket均未设置合规保留策略,否则报错The object you specified is immutable.
  • 拷贝文件时默认会覆盖同名文件, 为防止文件被意外覆盖,您可以通过以下方式保护您的文件。
    • 开启版本控制功能

      开启版本控制功能后,被删除或覆盖的文件会以历史版本的形式保存下来。您可以随时恢复历史版本文件。更多信息,请参见版本控制介绍

    • 在拷贝请求中携带禁止覆盖同名文件的参数

      在拷贝请求的Header中携带 x-oss-forbid-overwrite参数,并指定其值为true。当您拷贝的文件在目标Bucket中存在同名文件时,该文件将拷贝失败,并返回FileAlreadyExists错误。

使用图形化管理工具ossbrowser

通过ossbrowser仅支持拷贝小于5 GB的文件。关于如何使用ossbrowser拷贝文件的具体操作,请参见快速使用ossbrowser

使用阿里云SDK

以下仅列举常见SDK通过CopyObject方法拷贝小于1 GB文件的代码示例。关于其他SDK的拷贝小于1 GB文件以及通过UploadPartCopy方法拷贝大于1 GB文件的代码示例,请参见SDK简介

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写源Bucket名称。
        String sourceBucketName = "srcexamplebucket";
        // 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。
        String sourceKey = "srcexampleobject.txt";
        // 填写与源Bucket处于同一地域的目标Bucket名称。
        String destinationBucketName = "desexamplebucket";
        // 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。
        String destinationKey = "desexampleobject.txt";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建CopyObjectRequest对象。
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceKey, destinationBucketName, destinationKey);

            // 设置新的文件元信息。
            ObjectMetadata meta = new ObjectMetadata();
            meta.setContentType("text/txt");
            // 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
            // meta.setHeader("x-oss-forbid-overwrite", "true");
            // 指定拷贝的源地址。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE, "/examplebucket/recode-test.txt");
            // 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作,并返回200 OK。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
            // 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作,并返回200 OK。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_NONE_MATCH, "5B3C1A2E053D763E1B002CC607C5****");
            // 如果指定的时间等于或者晚于文件实际修改时间,则正常拷贝文件,并返回200 OK。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_UNMODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
            // 如果源Object在指定时间后被修改过,则执行拷贝操作。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_SOURCE_IF_MODIFIED_SINCE, "2021-12-09T07:01:56.000Z");
            // 指定设置目标Object元信息的方式。此处设置为COPY,表示复制源Object的元数据到目标Object。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_METADATA_DIRECTIVE, "COPY");
            // 指定OSS创建目标Object时使用的服务器端加密算法。
            // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
            // 表示KMS托管的用户主密钥,该参数仅在x-oss-server-side-encryption为KMS时有效。
            // meta.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
            // 指定OSS创建目标Object时的访问权限,此处设置为Private,表示只有Object的拥有者和授权用户有该Object的读写权限,其他用户没有权限操作该Object。
            // meta.setHeader(OSSHeaders.OSS_OBJECT_ACL, CannedAccessControlList.Private);
            // 指定Object的存储类型。此处设置为Standard,表示标准存储类型。
            // meta.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
            // 指定Object的对象标签,可同时设置多个标签。
            // meta.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
            // 指定设置目标Object对象标签的方式。此处设置为COPY,表示复制源Object的对象标签到目标Object。
            // meta.setHeader(OSSHeaders.COPY_OBJECT_TAGGING_DIRECTIVE, "COPY");
            copyObjectRequest.setNewObjectMetadata(meta);

            // 复制文件。
            CopyObjectResult result = ossClient.copyObject(copyObjectRequest);
            System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}                 
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;

// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
$endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 填写源Bucket名称,例如srcexamplebucket。
$from_bucket = "srcexamplebucket";
// 填写源Object的完整路径。Object完整路径中不能包含Bucket名称,例如srcdir/exampleobject.txt。
$from_object = "srcdir/exampleobject.txt";
// 填写与源Bucket处于同一地域的目标Bucket名称,例如destexamplebucket。
// 当在同一个Bucket内拷贝文件时,请确保源Bucket名称和目标Bucket名称相同。
$to_bucket = "destexamplebucket";
// 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称,例如destdir/exampleobject.txt。
$to_object = "destdir/exampleobject.txt";

$options = array(
    'headers'=>array(
      // 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
      // 'x-oss-forbid-overwrite' => 'true',
      // 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作,并返回200 OK。
      // 'x-oss-copy-source-if-match' => '5B3C1A2E053D763E1B002CC****',
      // 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作,并返回200 OK。
      // 'x-oss-copy-source-if-none-match' => '5B3C1A2E053D763E1B002CC****',
      // 如果指定的时间等于或者晚于文件实际修改时间,则正常拷贝文件,并返回200 OK。
      // 'x-oss-copy-source-if-unmodified-since' => gmdate('2021-12-09T07:01:56.000Z'),
      // 如果指定的时间早于文件实际修改时间,则正常拷贝文件,并返回200 OK。
      // 'x-oss-copy-source-if-modified-since' => gmdate('2021-12-09T07:01:56.000Z'),
      // 指定设置目标Object元信息的方式。此处设置为COPY,表示复制源Object的元数据到目标Object。
      // 'x-oss-metadata-directive' => 'COPY',
      // 指定OSS创建目标Object时使用的服务器端加密算法。
      // 'x-oss-server-side-encryption' => 'KMS',
      // 表示KMS托管的用户主密钥,该参数仅在x-oss-server-side-encryption为KMS时有效。
      // 'x-oss-server-side-encryption-key-id' => '9468da86-3509-4f8d-a61e-6eab****',
      // 指定OSS创建目标Object时的访问权限。此处设置为private,表示只有Object的拥有者和授权用户有该Object的读写权限,其他用户没有权限操作该Object。
      // 'x-oss-object-acl' => 'private',
      // 指定Object的存储类型。此处设置为Standard,表示标准存储类型。
      // 'x-oss-storage-class' => 'Standard',
      // 指定Object的对象标签,可同时设置多个标签。
      // 'x-oss-tagging' => 'k1=v1&k2=v2&k3=v3',
      // 指定设置目标Object对象标签的方式。此处设置为COPY,表示复制源Object的对象标签到目标Object。
      // 'x-oss-tagging-directive' => 'COPY',
    ),
);

try{
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);

    $ossClient->copyObject($from_bucket, $from_object, $to_bucket, $to_object);
} catch(OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": OK" . "\n");            
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);
})
# -*- coding: utf-8 -*-
import oss2

# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
auth = oss2.Auth('yourAccessKeyId', 'yourAccessKeySecret')
# 填写源Bucket名称,例如srcexamplebucket。
src_bucket_name = 'srcexamplebucket'
# 填写与源Bucket处于同一地域的目标Bucket名称,例如destexamplebucket。
# 当在同一个Bucket内拷贝文件时,请确保源Bucket名称和目标Bucket名称相同。
dest_bucket_name = 'destexamplebucket'
# yourEndpoint填写Bucket所在Region对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
bucket = oss2.Bucket(auth, 'yourEndpoint', dest_bucket_name)

# 填写不包含Bucket名称在内源Object的完整路径,例如srcexampleobject.txt。
src_object_name = 'srcexampleobject.txt'
# 填写不包含Bucket名称在内目标Object的完整路径,例如destexampleobject.txt。
dest_object_name = 'destexampleobject.txt'

# headers = dict()
# 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
# headers['x-oss-forbid-overwrite'] = 'true'
# 指定拷贝的源地址。
# headers[OSS_COPY_OBJECT_SOURCE] = '/example-bucket-by-util/recode-test.txt'
# 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作,并返回200 OK。
# headers['x-oss-copy-source-if-match'] = '5B3C1A2E053D763E1B002CC607C5****'
# 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作,并返回200 OK。
# headers['x-oss-copy-source-if-none-match'] = '5B3C1A2E053D763E1B002CC607C5****'
# 如果指定的时间等于或者晚于文件实际修改时间,则正常拷贝文件,并返回200 OK。
# headers['x-oss-copy-source-if-unmodified-since'] = '2021-12-09T07:01:56.000Z'
# 如果源Object在指定时间后被修改过,则执行拷贝操作。
# headers['x-oss-copy-source-if-modified-since'] = '2021-12-09T07:01:56.000Z'
# 指定设置目标Object元信息的方式。此处设置为COPY,表示复制源Object的元数据到目标Object。
# headers[OSS_METADATA_DIRECTIVE] = 'COPY'
# 指定OSS创建目标Object时使用的服务器端加密算法。
# headers[OSS_SERVER_SIDE_ENCRYPTION] = 'KMS'
# 表示KMS托管的用户主密钥,该参数仅在x-oss-server-side-encryption为KMS时有效。
# headers['x-oss-server-side-encryption-key-id'] = '9468da86-3509-4f8d-a61e-6eab1eac****'
# 指定OSS创建目标Object时的访问权限。此处设置为OBJECT_ACL_PRIVATE,表示只有Object的拥有者和授权用户有该Object的读写权限,其他用户没有权限操作该Object。
# headers[OSS_OBJECT_ACL] = oss2.OBJECT_ACL_PRIVATE
# 指定Object的存储类型。此处设置为BUCKET_STORAGE_CLASS_STANDARD,表示标准存储类型。
# headers['x-oss-storage-class'] = oss2.BUCKET_STORAGE_CLASS_STANDARD
# 指定Object的对象标签,可同时设置多个标签。
# headers[OSS_OBJECT_TAGGING] = 'k1=v1&k2=v2&k3=v3'
# 指定设置目标Object对象标签的方式。此处设置为COPY,表示复制源Object的对象标签到目标Object。
# headers[OSS_OBJECT_TAGGING_COPY_DIRECTIVE] = 'COPY'
# result = bucket.copy_object(src_bucket_name, src_object_name, dest_object_name, headers=headers)

# 将源Bucket中的某个Object拷贝到目标Bucket。
result = bucket.copy_object(src_bucket_name, src_object_name, dest_object_name)

# 查看返回结果的状态。如果返回值为200,表示执行成功。
print('result.status:', result.status)
using Aliyun.OSS;
using Aliyun.OSS.Common;

// 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// 填写源Bucket名称,例如srcexamplebucket。
var sourceBucket = "srcexamplebucket";
// 填写源Object的完整路径,完整路径中不能包含Bucket名称,例如srcdir/scrobject.txt。
var sourceObject = "srcdir/scrobject.txt";
// 填写与源Bucket处于同一地域的目标Bucket名称,例如destbucket。
var targetBucket = "destbucket";
// 填写目标Object的完整路径,完整路径中不能包含Bucket名称,例如destdir/destobject.txt。
var targetObject = "destdir/destobject.txt";

// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
try
{
    var metadata = new ObjectMetadata();
    metadata.AddHeader("mk1", "mv1");
    metadata.AddHeader("mk2", "mv2");
    var req = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject)
    {
        // 如果NewObjectMetadata为null则为COPY模式(即拷贝源文件的元信息),非null则为REPLACE模式(覆盖源文件的元信息)。
        NewObjectMetadata = metadata 
    };
    // 拷贝文件。
    client.CopyObject(req);
    Console.WriteLine("Copy object succeeded");
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2} \tHostID: {3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}
// 填写源Bucket名称。
String srcBucketName = "srcbucket";
// 填写源Bucket内的Object完整路径。
String srcObjectKey = "dir1/srcobject.txt";
// 填写与源Bucket处于同一地域的目标Bucket名称。
String destBucketName = "destbucket";
// 填写目标Bucket内的Object完整路径。
String destObjectKey = "dir2/destobject.txt";
// 创建Copy请求。
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcObjectKey, destBucketName, destObjectKey);

// ObjectMetadata objectMetadata = new ObjectMetadata();
// 设置Object的访问权限。此处设置有private,表示私有访问权限。
// objectMetadata.setHeader("x-oss-object-acl", "private");
// 设置Object存储类型。此处设置为Standard,表示标准存储类型。
// objectMetadata.setHeader("x-oss-storage-class", "Standard");
// 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
// objectMetadata.setHeader("x-oss-forbid-overwrite", "true");
// 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作。
// objectMetadata.setHeader("x-oss-copy-source-if-match", "5B3C1A2E053D763E1B002CC607C5****");
// 指定拷贝的源地址。
// objectMetadata.setHeader("x-oss-copy-source", "/examplebucket/recode-test.txt");
// 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作。
// objectMetadata.setHeader("x-oss-copy-source-if-none-match", "5B3C1A2E053D763E1B002CC607C5****");
// 如果指定的时间等于或者晚于文件实际修改时间,则执行拷贝操作。
// objectMetadata.setHeader("x-oss-copy-source-if-unmodified-since", "2021-12-09T07:01:56.000Z");
// 如果源Object在指定时间后被修改过,则执行拷贝操作。
// objectMetadata.setHeader("x-oss-copy-source-if-modified-since", "2021-12-09T07:01:56.000Z");
// 指定设置目标Object元信息的方式。此处设置为COPY,表示复制源Object的元数据到目标Object。
// objectMetadata.setHeader("x-oss-metadata-directive", "COPY");
// 指定OSS创建目标Object时使用的服务器端加密算法。
// objectMetadata.setHeader("x-oss-server-side-encryption", "SSE-KMS");
// 表示KMS托管的用户主密钥,该参数仅在x-oss-server-side-encryption为KMS时有效。
// objectMetadata.setHeader("x-oss-server-side-encryption-key-id", "9468da86-3509-4f8d-a61e-6eab1eac****");
// 指定Object的对象标签,可同时设置多个标签。
// objectMetadata.setHeader("x-oss-tagging", "a:1");
// 指定设置目标Object对象标签的方式。此处设置为COPY,表示复制源Object的对象标签到目标Object。
// objectMetadata.setHeader("x-oss-tagging-directive", "COPY");

// 异步Copy。
OSSAsyncTask copyTask = oss.asyncCopyObject(copyObjectRequest, new OSSCompletedCallback<CopyObjectRequest, CopyObjectResult>() {
    @Override
    public void onSuccess(CopyObjectRequest request, CopyObjectResult result) {
        Log.d("copyObject", "copy success!");
    }

    @Override
    public void onFailure(CopyObjectRequest request, ClientException clientExcepion, ServiceException serviceException) {
        // 请求异常。
        if (clientExcepion != null) {
            // 客户端异常,例如网络异常等。
            clientExcepion.printStackTrace();
        }
        if (serviceException != null) {
            // 服务端异常。
            Log.e("ErrorCode", serviceException.getErrorCode());
            Log.e("RequestId", serviceException.getRequestId());
            Log.e("HostId", serviceException.getHostId());
            Log.e("RawMessage", serviceException.getRawMessage());
        }
    }
});
package main

import (
    "fmt"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
    "os"
    "time"
)

func main() {
    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // 填写Bucket名称,例如examplebucket。
    bucketName := "examplebucket"
    // 填写拷贝前文件的完整路径,例如srcdir/srcobject.jpg。
    objectName := "srcdir/srcobject.jpg"
    // 填写拷贝后文件的完整路径,例如destdir/destobject.jpg。
    destObjectName := "destdir/destobject.jpg"

    // 获取存储空间。
    bucket, err := client.Bucket(bucketName)
    if err != nil {
        fmt.Println("Error:", err)

        os.Exit(-1)
    }

    //指定目标文件的元信息。
    expires := time.Date(2049, time.January, 10, 23, 0, 0, 0, time.UTC)
    tag1 := oss.Tag{
        Key:   "a",
        Value: "1",
    }

    taggingInfo := oss.Tagging{
        Tags: []oss.Tag{tag1},
    }

    options := []oss.Option{
        oss.MetadataDirective(oss.MetaReplace),
        oss.Expires(expires),
        oss.SetTagging(taggingInfo),
        // 指定复制源Object的对象标签到目标 Object。
        // oss.TaggingDirective(oss.TaggingCopy),
        // 指定创建目标Object时的访问权限ACL为私有。    
        // oss.ObjectACL(oss.ACLPrivate),
        // 指定KMS托管的用户主密钥,该参数仅在x-oss-server-side-encryption为KMS时有效。
        //oss.ServerSideEncryptionKeyID("9468da86-3509-4f8d-a61e-6eab1eac****"),
        // 指定OSS创建目标Object时使用的服务器端加密算法。
        // oss.ServerSideEncryption("AES256"),
        // 指定复制源Object的元数据到目标Object。
        //oss.MetadataDirective(oss.MetaCopy),
        // 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
        // oss.ForbidOverWrite(true),
        // 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作,并返回200 OK。
        //oss.CopySourceIfMatch("5B3C1A2E053D763E1B002CC607C5****"),
        // 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作,并返回200 OK。
        //oss.CopySourceIfNoneMatch("5B3C1A2E053D763E1B002CC607C5****"),
        // 如果指定的时间早于文件实际修改时间,则正常拷贝文件,并返回200 OK。
        //oss.CopySourceIfModifiedSince(2021-12-09T07:01:56.000Z),
        // 如果指定的时间等于或者晚于文件实际修改时间,则正常拷贝文件,并返回200 OK。
        //oss.CopySourceIfUnmodifiedSince(2021-12-09T07:01:56.000Z),
        // 指定Object的存储类型。此处设置为Standard,表示标准存储类型。
        //oss.StorageClass("Standard"),
        }

    // 使用指定的元信息覆盖源文件的元信息。
    _, err = bucket.CopyObject(objectName, destObjectName, options...)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}
OSSCopyObjectRequest * copy = [OSSCopyObjectRequest new];
// 填写源Bucket名称。
copy.sourceBucketName = @"sourcebucket";
// 填写源Bucket内的Object完整路径。
copy.sourceObjectKey = @"dir1/srcobject.txt";
// 填写目标Bucket名称。
copy.bucketName = @"destbucket";
// 填写目标Bucket内的Object完整路径。
copy.objectKey = @"dir2/destobject.txt";
NSMutableDictionary *objectMeta = [NSMutableDictionary dictionary];
// 设置访问权限。此处设置为private,表示私有权限。
[objectMeta setValue:@"x-oss-object-acl" forKey:@"public-read"];
// 设置存储类型。此处设置为Standard,表示标准存储类型。
[objectMeta setValue:@"x-oss-storage-class" forKey:@"Standard"];
// 是否覆盖同名Object。不指定x-oss-forbid-overwrite时,默认覆盖同名Object。
// 指定x-oss-forbid-overwrite为false时,表示允许覆盖同名Object。指定x-oss-forbid-overwrite为true时,表示禁止覆盖同名Object,如果同名Object已存在,程序将报错。
[objectMeta setValue:@"x-oss-forbid-overwrite" forKey:@"true"];
// 如果源Object的ETag值和您提供的ETag相等,则执行拷贝操作。
[objectMeta setValue:@"x-oss-copy-source-if-match" forKey:@"5B3C1A2E053D763E1B002CC607C5****"];
// 如果源Object的ETag值和您提供的ETag不相等,则执行拷贝操作。
[objectMeta setValue:@"x-oss-copy-source-if-none-match" forKey:@"5B3C1A2E053D763E1B002CC607C5****"];
// 如果文件实际修改时间早于或等于2021-12-09T07:01:56.000Z,则执行拷贝操作。
[objectMeta setValue:@"x-oss-copy-source-if-unmodified-since" forKey:@"2021-12-09T07:01:56.000Z"];
// 如果文件实际修改时间晚于2021-12-15T07:01:56.000Z,则执行拷贝操作。
[objectMeta setValue:@"x-oss-copy-source-if-modified-since" forKey:@"2021-12-15T07:01:56.000Z"];
// 复制源Object的元数据到目标Object。
[objectMeta setValue:@"x-oss-metadata-directive" forKey:@"COPY"];
// 复制源Object的对象标签到目标Object。
[objectMeta setValue:@"x-oss-tagging-directive" forKey:@"Copy"];
// 指定OSS创建目标Object时使用的服务器端加密算法。
[objectMeta setValue:@"x-oss-server-side-encryption" forKey:@"KMS"];
// 表示KMS托管的用户主密钥,该参数仅在x-oss-server-side-encryption为KMS时有效。
[objectMeta setValue:@"x-oss-server-side-encryption-key-id" forKey:@"9468da86-3509-4f8d-a61e-6eab1eac****"];
copy.objectMeta = objectMeta;


OSSTask * task = [client copyObject:copy];
[task continueWithBlock:^id(OSSTask *task) {
    if (!task.error) {
        NSLog(@"copy object success!");
    } else {
        NSLog(@"copy object failed, error: %@" , task.error);
    }
    return nil;
}];
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
    /* 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。*/
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    /* 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
    /* 填写源Bucket名称,例如srcexamplebucket。*/
    std::string SourceBucketName = "srcexamplebucket";
    /* 填写与源Bucket处于同一地域的目标Bucket名称,例如destbucket。*/
    std::string CopyBucketName = "destbucket";
    /* 填写源Object的完整路径,完整路径中不能包含Bucket名称,例如srcdir/scrobject.txt。*/
    std::string SourceObjectName = "srcdir/scrobject.txt";
    /* 填写目标Object的完整路径,完整路径中不能包含Bucket名称,例如destdir/destobject.txt。*/
    std::string CopyObjectName = "destdir/destobject.txt";

    /* 初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    CopyObjectRequest request(CopyBucketName, CopyObjectName);
    request.setCopySource(SourceBucketName, SourceObjectName);

    /* 拷贝文件。*/
    auto outcome = client.CopyObject(request);

    if (!outcome.isSuccess()) {
        /* 异常处理。*/
        std::cout << "CopyObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        ShutdownSdk();
        return -1;
    }

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
const char *endpoint = "<yourEndpoint>";
const char *access_key_id = "<yourAccessKeyId>";
const char *access_key_secret = "<yourAccessKeySecret>";
const char *bucket_name = "<yourBucketName>";
const char *object_name = "<yourObjectName>";
const char *source_bucket_name = "<yourSourceBucketName>";
const char *source_object_name = "<yourSourceObjectName>";
const char *dest_bucket_name = "<yourDestBucketName>";
const char *dest_object_name = "<yourDestObjectName>";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* 用char*类型的字符串初始化aos_string_t类型。*/
    aos_str_set(&options->config->endpoint, endpoint);
    aos_str_set(&options->config->access_key_id, access_key_id);
    aos_str_set(&options->config->access_key_secret, access_key_secret);
    /* 是否使用了CNAME。0表示不使用。*/
    options->config->is_cname = 0;
    /* 用于设置网络相关参数,比如超时时间等。*/
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
    /* 在程序入口调用aos_http_io_initialize方法来初始化网络、内存等全局资源。*/
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* 用于内存管理的内存池(pool),等价于apr_pool_t。其实现代码在apr库中。*/
    aos_pool_t *pool;
    /* 重新创建一个内存池,第二个参数是NULL,表示没有继承其它内存池。*/
    aos_pool_create(&pool, NULL);
    /* 创建并初始化options,该参数包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全局配置信息。*/
    oss_request_options_t *oss_client_options;
    /* 在内存池中分配内存给options。*/
    oss_client_options = oss_request_options_create(pool);
    /* 初始化Client的选项oss_client_options。*/
    init_options(oss_client_options);
    /* 初始化参数。*/
    aos_string_t source_bucket;
    aos_string_t source_object;
    aos_string_t dest_bucket;
    aos_string_t dest_object;
    aos_table_t *headers = NULL;
    aos_table_t *resp_headers = NULL; 
    aos_status_t *resp_status = NULL; 
    aos_str_set(&source_bucket, source_bucket_name);
    aos_str_set(&source_object, source_object_name);
    aos_str_set(&dest_bucket, dest_bucket_name);
    aos_str_set(&dest_object, dest_object_name);
    headers = aos_table_make(pool, 0);
    /* 拷贝文件。*/
    resp_status = oss_copy_object(oss_client_options, &source_bucket, &source_object, &dest_bucket, &dest_object, headers, &resp_headers);
    if (aos_status_is_ok(resp_status)) {
        printf("copy object succeeded\n");
    } else {
        printf("copy object failed\n");
    }
    /* 释放内存池,相当于释放了请求过程中各资源分配的内存。*/
    aos_pool_destroy(pool);
    /* 释放之前分配的全局资源。*/
    aos_http_io_deinitialize();
    return 0;
}
require 'aliyun/oss'
client = Aliyun::OSS::Client.new(
  # 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

# 填写Bucket名称,例如examplebucket。
bucket = client.get_bucket('examplebucket')

# 拷贝文件元信息。
bucket.copy_object(
  'my-object', 'copy-object',
  :meta_directive => Aliyun::OSS::MetaDirective::COPY)

# 覆盖文件元信息。
bucket.copy_object(
  'my-object', 'copy-object',
  :metas => {'year' => '2017'},
  :meta_directive => Aliyun::OSS::MetaDirective::REPLACE)            

使用命令行工具ossutil

关于使用ossutil拷贝文件的具体操作, 请参见拷贝文件

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见CopyObject