本文介绍如何将源Bucket中的文件(Object)复制到同一地域下相同或不同目标Bucket中。
注意事项
本文以华东1(杭州)外网Endpoint为例。如果您希望通过与OSS同地域的其他阿里云产品访问OSS,请使用内网Endpoint。关于OSS支持的Region与Endpoint的对应关系,请参见访问域名和数据中心。
本文以OSS域名新建OSSClient为例。如果您希望通过自定义域名、STS等方式新建OSSClient,请参见初始化。
拷贝文件时,您必须拥有源文件的读权限及目标Bucket的读写权限。
拷贝文件时,您需要确保源Bucket和目标Bucket均未设置合规保留策略,否则报错The object you specified is immutable.。
不支持跨地域拷贝。例如不能将华东1(杭州)地域存储空间中的文件拷贝到华北1(青岛)地域。
拷贝小文件
以下代码用于拷贝小文件:
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";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写源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();
// 设置自定义元数据。自定义元数据为键值对(Key-Value)的形式,例如Key为mk1,Value为mv1。
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);
}
拷贝大文件
分片拷贝
对于大于1 GB的文件,需要使用分片拷贝(UploadPartCopy)。分片拷贝分为三步:
使用InitiateMultipartUploadRequest方法来初始化一个分片上传事件。
使用UploadPartCopy方法进行分片拷贝。
使用CompleteMultipartUpload方法完成文件拷贝。
以下代码用于分片拷贝文件:
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"; // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID"); var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET"); // 填写源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"; var uploadId = ""; var partSize = 50 * 1024 * 1024; // 创建OssClient实例。 var client = new OssClient(endpoint, accessKeyId, accessKeySecret); try { // 初始化拷贝任务。可以通过InitiateMultipartUploadRequest指定目标文件元数据。 var request = new InitiateMultipartUploadRequest(targetBucket, targetObject); var result = client.InitiateMultipartUpload(request); // 打印uploadId。 uploadId = result.UploadId; Console.WriteLine("Init multipart upload succeeded, Upload Id: {0}", result.UploadId); // 计算分片数。 var metadata = client.GetObjectMetadata(sourceBucket, sourceObject); var fileSize = metadata.ContentLength; var partCount = (int)fileSize / partSize; if (fileSize % partSize != 0) { partCount++; } // 开始分片拷贝。 var partETags = new List<PartETag>(); for (var i = 0; i < partCount; i++) { var skipBytes = (long)partSize * i; var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes); // 创建UploadPartCopyRequest。可以通过UploadPartCopyRequest指定限定条件。 var uploadPartCopyRequest = new UploadPartCopyRequest(targetBucket, targetObject, sourceBucket, sourceObject, uploadId) { PartSize = size, PartNumber = i + 1, // BeginIndex用来定位此次上传分片开始所对应的位置。 BeginIndex = skipBytes }; // 调用uploadPartCopy方法来拷贝每一个分片。 var uploadPartCopyResult = client.UploadPartCopy(uploadPartCopyRequest); Console.WriteLine("UploadPartCopy : {0}", i); partETags.Add(uploadPartCopyResult.PartETag); } // 完成分片拷贝。 var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(targetBucket, targetObject, uploadId); // partETags为分片上传中保存的partETag的列表,OSS收到用户提交的此列表后,会逐一验证每个数据分片的有效性。全部验证通过后,OSS会将这些分片合成一个完整的文件。 foreach (var partETag in partETags) { completeMultipartUploadRequest.PartETags.Add(partETag); } var completeMultipartUploadResult = client.CompleteMultipartUpload(completeMultipartUploadRequest); Console.WriteLine("CompleteMultipartUpload 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); }
断点续传拷贝
如果拷贝中断,可通过断点续传继续拷贝。
以下代码用于断点续传拷贝:
using Aliyun.OSS; // 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。 var endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。 var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID"); var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET"); // 填写源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"; // 记录拷贝结果的文件。拷贝过程中的进度信息会保存在该文件中,如果拷贝失败,再次拷贝时会根据文件中记录的点继续拷贝。拷贝完成后,该文件会被删除。 var checkpointDir = @"yourCheckpointDir"; // 创建OssClient实例。 var client = new OssClient(endpoint, accessKeyId, accessKeySecret); try { var request = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject); // checkpointDir目录中会保存断点续传的中间状态,用于失败后,下次继续拷贝。如果checkpointDir为null,断点续传功能不会生效,每次都会重新拷贝。 client.ResumableCopyObject(request, checkpointDir); Console.WriteLine("Resumable copy new object:{0} succeeded", request.DestinationKey); } catch (Exception ex) { Console.WriteLine("Resumable copy new object failed, {0}", ex.Message); }
相关文档
拷贝小文件
关于拷贝小文件的完整示例代码,请参见GitHub示例。
关于拷贝小文件的API接口说明,请参见CopyObject。
拷贝大文件
关于拷贝大文件的完整示例代码,请参见GitHub示例。
关于拷贝大文件的API接口说明,请参见UploadPartCopy。
断点续传拷贝
关于断点续传拷贝的完整示例代码,请参见GitHub示例。