全部產品
Search
文件中心

Object Storage Service:.NET拷貝檔案

更新時間:Nov 26, 2024

本文介紹如何將源Bucket中的檔案(Object)複製到同一地區下相同或不同目標Bucket中。

注意事項

  • 本文以華東1(杭州)外網Endpoint為例。如果您希望通過與OSS同地區的其他阿里雲產品訪問OSS,請使用內網Endpoint。關於OSS支援的Region與Endpoint的對應關係,請參見OSS地區和訪問網域名稱

  • 本文以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";
// 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。
const string region = "cn-hangzhou";

// 建立ClientConfiguration執行個體,按照您的需要修改預設參數。
var conf = new ClientConfiguration();

// 設定v4簽名。
conf.SignatureVersion = SignatureVersion.V4;

// 建立OssClient執行個體。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
c.SetRegion(region);
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)。分區拷貝分為三步:

    1. 使用InitiateMultipartUploadRequest方法來初始化一個分區上傳事件。

    2. 使用UploadPartCopy方法進行分區拷貝。

    3. 使用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;
    // 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。
    const string region = "cn-hangzhou";
    
    // 建立ClientConfiguration執行個體,按照您的需要修改預設參數。
    var conf = new ClientConfiguration();
    
    // 設定v4簽名。
    conf.SignatureVersion = SignatureVersion.V4;
    
    // 建立OssClient執行個體。
    var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
    c.SetRegion(region);
    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";
    // 填寫Bucket所在地區對應的Region。以華東1(杭州)為例,Region填寫為cn-hangzhou。
    const string region = "cn-hangzhou";
    
    // 建立ClientConfiguration執行個體,按照您的需要修改預設參數。
    var conf = new ClientConfiguration();
    
    // 設定v4簽名。
    conf.SignatureVersion = SignatureVersion.V4;
    
    // 建立OssClient執行個體。
    var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
    c.SetRegion(region);
    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樣本