閱讀82 返回首頁    go 網易 go 網易蜂巢


對象存儲 .NET SDK

目錄

安裝

SDK

曆史版本: 無

環境要求

Windows

 1. 適用於.NET 4.5 及以上版本
 2. 適用於Visual Studio 2010及以上版本

安裝

NuGet安裝

 1. 如果您的Visual Studio沒有安裝NuGet,請先安裝 NuGet。
 2. 安裝好NuGet後,先在Visual Studio中新建或者打開已有的項目,然後選擇<工具>-<NuGet程序包管理器>-<管理解決方案的NuGet程序包>。
 3. 搜索nos-dotnet-sdk,在結果中找到Netease.Cloud.NOS.C#.SDK,選擇最新版本,點擊安裝,成功後添加到項目應用中。

DLL引入方式安裝

 1. 從以下 鏈接 下載SDK包,解壓後bin目錄包括了nos-dotnet-sdk.dll文件。
 2. 在Visual Studio的<解決方案資源管理器>中選擇您的項目,然後右鍵<項目名稱>-<引用>,在彈出的菜單中選擇<添加引用>, 在彈出<添加引用>對話框後,選擇<瀏覽>,找到SDK包解壓的目錄,在bin目錄下選中<nos-dotnet-sdk.dll>文件,點擊確定即可

初始化

確定EndPoint

EndPoint 是NOS各個區域的地址,目前支持以下形式

EndPoint類型 備注
NOS區域域名地址 使用桶所在的區域的NOS域名地址

NOS區域域名地址

進入NOS控製台,在桶的 屬性 中可以查找到當前桶所在的區域及域名,桶的域名的後綴部分為 該桶的公網域名,例如:test-logging.nos-eastchina1.126.net中的nos-eastchina1.126.net 為該桶的公網EndPoint。

配置秘鑰

要接入NOS服務,您需要一對有效的AccessKey(包括AccessKeyId與AccessKeySecret)來進行 簽名驗證,開通服務與AccessKey請參考 訪問控製

在獲取到AccessKeyId與AccessKeySecret之後,可以按照以下的步驟進行初始化

新建NosClient

使用NOS地區域名創建NosClient

初始化代碼如下所示:

using Netease.Cloud.NOS;

const string accessKeyId = "your-accessKeyId";
const string accessKeySecret  = "your-accessKeySecret";
const string endponit = "建桶時選擇的的區域域名";

/// <summary>
/// 配置構造一個<see cref="NOSClient"/>實例
/// </summary>
/// <param name="endpoint">NOS訪問地址</param>
/// <param name="accessKeyId">NOS的訪問ID</param>
/// <param name="accessKeySecret">NOS訪問密鑰</param>
var nosClient = new NosClient(endponit, accessKeyId, accessKeySecret);

設置網絡參數

如果您需要修改NosClient的默認參數,可以在實例化NosClient時傳入ClientConfiguration實例。ClientConfiguration是NosClient的配置類,可配置連接超時、最大連接數等參數:

ClientConfiguration conf = new ClientConfiguration();

// 設置NosClient連接超時時間,單位:毫秒
conf.ConnectionTimeout = 50000;
// 設置NosClient使用的最大連接數
conf.MaxConnections(200);
// 設置socket超時時間,單位:毫秒
conf.SocketTimeout(10000);
// 設置失敗請求重試次數
conf.MaxErrorRetry(2);

var nosClient = new NosClient(endponit, accessKeyId, accessKeySecret, conf);

快速入門

使用NOS C# SDK前,您可以先參照 API 手冊 熟悉NOS的基本概念,如Bucket、Object、EndPoint、AccessKeyId和AccessKeySecret等。 本節您將看到如何快速的使用NOS C# SDK,完成常用的操作,上傳文件、下載文件等。

常用類

常用類 備注
NOS\NosClient NOS客戶端類,用戶通過NosClient調用服務
NOS\Exception\NosException NOS異常,在調用過程中去捕獲這個異常,查看失敗原因

基本操作

上傳文件

對象(Object)是NOS中最基本的數據單元,您可以把它簡單的理解為文件,以下代碼可以實現簡單的對象上傳:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 上傳文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="fileToUpload">上傳的文件</param>
public void PutObject(string bucket, string key, string fileToUpload)
{
    try
    {
        nosClient.PutObject(bucket, key, fileToUpload)
        Console.WriteLine("Put object:{0} succeeded", key);
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 對象命名規則請參見 API 手冊 對象
 2. NOS-C#-SDK中對象名不支持三種特殊字符:* / ~
 3. 更多的上傳文件信息,請參見 NOS-C#-SDK 上傳文件

下載文件

上傳對象成功之後,您可以讀取它的內容,以下代碼可以實現文件的下載:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 上傳文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="dirToDownload">下載文件存放的目錄</param>
public void GetObject(string bucket, string key, string dirToDownload)
{
    try
    {
        nosClient.GetObject(bucket, key, dirToDownload + "/sample.data");
        Console.WriteLine("Get object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
            ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

更多的下載文件信息,請參見 NOS C# SDK 下載文件

列舉文件

當上傳文件成功之後,可以查看桶中包含的文件列表,以下代碼展示如何列舉桶內的文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 列舉桶內文件
/// </summary>
/// <param name="bucket">桶名</param>
public void ListObjects(string bucket)
{
    try
    {
        var keys = new List<string>();
        var listObjectsRequest = new ListObjectsRequest(bucket);
        ObjectListing result = nosClient.ListObjects(listObjectsRequest);
        foreach (var summary in result.ObjectSummarise)
        {
            Console.WriteLine(summary.Key);
            keys.Add(summary.Key);
        }

        Console.WriteLine("List objects of bucket:{0} succeeded ", bucket);
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
            ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Note:

 1. 上麵的代碼默認列舉100個object

更多的管理文件信息,請參見 NOS C# SDK 文件管理

刪除文件

文件上傳成功後,可以指定刪除桶中的文件,以下代碼實現桶中文件的刪除:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 刪除單個文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
public void DeleteObject(string bucket, string key)
{
    try
    {
        nosClient.DeleteObject(bucket, key);
        Console.WriteLine("Delete object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
        ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

返回結果處理

NosClient中的接口對應返回數據分為兩類:

 1. Put,Delete類接口返回null,如果沒有NosException,即可認為操作成功
 2. Get,List類接口返回對應的數據,如果沒有NosException,即可認為操作成功

例如:

try
{
    ObjectListing result = nosClient.ListObjects(listObjectsRequest);
    foreach (var summary in result.ObjectSummarise)
    {
        Console.WriteLine(summary.Key);
    }
}
catch (NosException ex)
{
    Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
        ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}

文件上傳

在NOS中用戶的基本操作單元是對象,亦可以理解為文件,NOS C# SDK提供了豐富的上傳接口,可以通過以下的方式上傳文件:

 1. 流式上傳
 2. 單塊上傳
 3. 分塊上傳

流式上傳、單塊上傳最大為100M;分塊上傳除最後一塊外,分塊不能小於16k,每一個分塊不能大於100M,最多能上傳10000個分塊,即分塊上傳的文件最大支持1T。

流式上傳

您可以使用NosClient.PutObject上傳一個一個Stream中的內容,具體實現如下:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 流式上傳
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="content">需要上傳的流</param>
public void PutObject(string bucket, string key, Stream content)
{
    try
    {
        nosClient.PutObject(bucket, key, content);
        Console.WriteLine("Put object:{0} succeeded", key);
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 上傳的流內容不超過100M

單塊上傳

您可以使用NosClient.PutObject上傳文件內容,具體實現如下:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 上傳文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="fileToUpload">上傳的文件</param>
public void PutObject(string bucket, string key, string fileToUpload)
{
    try
    {
        nosClient.PutObject(bucket, key, fileToUpload);
        Console.WriteLine("Put object:{0} succeeded", key);
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
            ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 上傳的文件內容不超過100M

分塊上傳

除了通過putObject接口上傳文件到NOS之外,NOS還提供了另外一種上傳模式-分塊上傳,用戶可以在如下應用場景內(但不限於此),使用分塊上傳模式,如:

 1. 需支持斷點上傳
 2. 上傳超過100M的文件
 3. 網絡條件較差,經常和NOS服務器斷開連接
 4. 上傳文件之前無法確定文件的大小

分塊上傳一般流程如下所示:

 1. 初始化一個分塊上傳任務(InitiateMultipartUpload)
 2. 上傳分塊(UploadPart)
 3. 完成分塊上傳(CompleteMultipartUpload)或者取消分塊上傳(AbortMultipartUpload)

初始化分塊上傳

您可以使用NosClient.InitiateMultipartUpload初始化分塊上傳,具體實現如下:


// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 初始化分塊上傳
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
public string InitiateMultipartUpload(String bucket, String key)
{
    string uploadId = "";
    try
    {
        var request = new InitiateMultipartUploadRequest(bucket, key);
        var result = nosClient.InitiateMultipartUpload(request);
        uploadId = result.UploadId;

        Console.WriteLine("Init multipart upload succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
            ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }

    return uploadId;
}

上傳分塊

您可以使用NosClient.UploadPart上傳分塊,具體實現如下:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 上傳分塊
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="fileToUpload">上傳的文件</param>
/// <param name="uploadId">分塊上傳的ID</param>
/// <param name="partSize">分塊大小</param>
public List<PartETag> UploadParts(String bucket, String key, String fileToUpload,
                              String uploadId, int partSize)
{
    // 計算片個數
    var fi = new FileInfo(fileToUpload);
    var fileSize = fi.Length;
    var partCount = fileSize / partSize;
    if (fileSize % partSize != 0)
    {
        partCount++;
    }

    // 開始分片上傳
    var partETags = new List<PartETag>();
    try
    {
        using (var fs = File.Open(fileToUpload, FileMode.Open))
        {
            for (var i = 0; i < partCount; i++)
            {
                var skipBytes = (long)partSize * i;
                //定位到本次上傳片應該開始的位置
                fs.Seek(skipBytes, 0);
                var size = (partSize < fileSize - skipBytes) ? partSize : (fileSize - skipBytes);
                var request = new UploadPartRequest(bucket, objectName, uploadId)
                {
                    Content = fs,
                    PartSize = size,
                    PartNumber = i + 1
                };

                var result = nosClient.UploadPart(request);

                partETags.Add(result.PartETag);
            }
        }
        Console.WriteLine("Put multipart upload succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }

    return partETags;
}

完成分塊上傳

您可以使用NosClient.CompleteMultipartUpload完成上傳分塊,具體實現如下:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 完成分塊上傳
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="uploadId">分塊上傳的ID</param>
/// <param name="partETags">PartETag 對象,它是上傳塊的ETag與塊編號(PartNumber)的組合</param>
public void CompleteUploadPart(String bucket, String key,
                                            String uploadId, List<PartETag> partETags)
{
    try
    {
        var completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucket, key, uploadId);
        foreach (var partETag in partETags)
        {
            completeMultipartUploadRequest.PartETags.Add(partETag);
        }

        nosClient.CompleteMultipartUpload(completeMultipartUploadRequest);
        Console.WriteLine("Complete Upload Part succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

分塊上傳示例

下麵通過一個完整的示例說明了如何進行分片上傳操作,可以參考下麵代碼:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 分塊上傳示例
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="fileToUpload">上傳的文件</param>
public void UploadPart(string bucket, string key, string fileToUpload)
{
    try
    {
        /*
        * 初始化一個分塊上傳事件
        * */
        var initRequest = new InitiateMultipartUploadRequest(bucket, key);
        var initResult = nosClient.InitiateMultipartUpload(initRequest);

        /*
        * 上傳分塊
        * */

        // 設置每塊為 1M
        const int partSize = 1024 * 1024 * 100;

        var partFile = new FileInfo(fileToUpload);
        var fileSize = partFile.Length;
        // 計算分塊數目
        var partCount = fileSize / partSize;
        if (fileSize % partSize != 0)
        {
            partCount++;
        }

        // 新建一個List保存每個分塊上傳後的ETag和PartNumber
        var partETags = new List<PartETag>();
        //upload the file
        using (var fs = new FileStream(partFile.FullName, FileMode.Open))
        {
            for (var i = 0; i < partCount; i++)
            {
                // 跳到每個分塊的開頭
                long skipBytes = partSize * i;
                fs.Position = skipBytes;

                // 計算每個分塊的大小
                var size = partSize < partFile.Length - skipBytes
                    ? partSize
                    : partFile.Length - skipBytes;

                // 創建UploadPartRequest,上傳分塊
                var uploadPartRequest = new UploadPartRequest(bucket, key, initResult.UploadId)
                {
                    Content = fs,
                    PartSize = size,
                    PartNumber = (i + 1)
                };

                var uploadPartResult = nosClient.UploadPart(uploadPartRequest);

                // 將返回的PartETag保存到List中。
                partETags.Add(uploadPartResult.PartETag);

                /*
                * 完成分塊上傳事件
                * */
                var completeRequest = new CompleteMultipartUploadRequest(bucket, key, initResult.UploadId);
                foreach (var partETag in partETags)
                {
                    completeRequest.PartETags.Add(partETag);
                }
                nosClient.CompleteMultipartUpload(completeRequest);
            }
            fs.Close();
        }

        Console.WriteLine("Upload Part succeeded");
    }
    catch (NosException ex)
    {
            Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                    ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
            Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 上麵程序一共分為三個步驟:1. initiate 2. uploadPart 3. complete
 2. UploadPart 方法要求除最後一個Part以外,其他的Part大小都要大於或等於16K。但是Upload Part接口並不會立即校驗上傳Part的大小(因為不知道是否為最後一塊);隻有當Complete Multipart Upload的時候才會校驗。
 3. Part號碼的範圍是1~10000。如果超出這個範圍,NOS將返回InvalidArgument的錯誤碼。
 4. 分塊上傳除最後一塊外,分塊不能小於16k,每一個分塊不能大於100M。
 5. 每次上傳Part時都要把流定位到此次上傳塊開頭所對應的位置。
 6. 分片上傳任務初始化或上傳部分分片後,可以使用abortMultipartUpload接口中止分片上傳事件。當分片上傳事件被中止後,就不能再使用這個Upload ID做任何操作,已經上傳的分片數據也會被刪除。
 7. 每次上傳Part之後,NOS的返回結果會包含一個 PartETag 對象,它是上傳塊的ETag與塊編號(PartNumber)的組合。在後續完成分片上傳的步驟中會用到它,因此我們需要將其保存起來,然後在第三步complete的時候使用,具體操作參考上麵代碼。

取消分塊上傳

您可以使用NosClient.AbortMultipartUpload取消上傳事件,具體實現如下:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 取消分塊上傳
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="uploadId">分塊上傳的ID</param>
public void AbortMultipartUpload(string bucket, string key, string uploadId)
{
    try
    {
        var abortRequest = new AbortMultipartUploadRequest(bucket, key, uploadId);
        nosClient.AbortMultipartUpload(abortRequest);

        Console.WriteLine("Abort Multipart Upload succeeded");
        }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

查看已經上傳的分片

查看已經上傳的分片可以羅列出指定Upload ID(InitiateMultipartUpload時獲取)所屬的所有已經上傳成功的分片,您可以通過NosClient.ListParts接口獲取已經上傳的分片,可以參考以下代碼:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

// <summary>
/// 列出已上傳的分塊
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="uploadId">分塊上傳的ID</param>
public void ListParts(string bucket, string key, string uploadId)
{
    try
    {
        var listPartsRequest = new ListPartsRequest(bucket, key, uploadId){
            MaxParts = 10,
            PartMumberMarker = '10'
        }
        var result = nosClient.ListParts(listPartsRequest);
        Console.WriteLine("List parts succeeded");

        foreach (var part in result.Parts)
        {
            Console.WriteLine(part.ToString());
        }
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

查看已經上傳的分片可以指定以下參數:

參數 描述
MaxParts 響應中的limit個數 類型:整型
PartMumberMarker 分塊號的界限,隻有更大的分塊號會被列出來。 類型:字符串

查看當前正在進行的分片上傳任務

查看正在進行的分片上傳任務可以羅列出正在進行,還未完成的分片上傳任務,您可以通過NosClient.ListMultipartUploads接口當前的上傳任務,可以參考以下代碼:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

// <summary>
/// 查看當前正在進行的分片上傳任務
/// </summary>
/// <param name="bucket">桶名</param>
public void ListMultipartUploads(string bucket)
{
    try
    {
        var listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucket){
            KeyMarker = "",
            MaxUploads = 10
        };
        var result = nosClient.ListMultipartUploads(listMultipartUploadsRequest);

        Console.WriteLine("List multi Uploads succeeded");
        foreach (var mu in result.MultipartUploads)
        {
            Console.WriteLine("Key:{0}, UploadId:{1}", mu.Key , mu.UploadId);
        }
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

上述代碼中使用的options參數如下:

參數值 描述
KeyMarker 指定某一uploads key,隻有大於該KeyMarker的才會被列出
MaxUploads 最多返回MaxUploads條記錄,默認1000

設置文件元信息

文件元數據(object meta),是上傳到NOS的文件屬性描述信息,分為http標準屬性和用戶自定義元數據。文件元信息可以在各種上傳方式(流式上傳、單塊上傳、分塊上傳)時進行設置。

設定http header

NOS允許用戶自定義http Header。http header相關信息請參考 RFC2616,幾個常用的header說明如下:

名稱 描述 默認值
Content-MD5 文件數據校驗,設置了該值後NOS會啟用文件內容MD5校驗,把您提供的MD5與文件的MD5比較,不一致會拋出錯誤
Content-Type 文件的MIME,定義文件的類型及網頁編碼,決定瀏覽器將以什麼形式、什麼編碼讀取文件。如果用戶沒有指定則根據Key或文件名的擴展名生成,如果沒有擴展名則填默認值 application/octet-stream
Content-Disposition 指示MINME用戶代理如何顯示附加的文件,打開或下載,及文件名稱
Content-Length 上傳的文件的長度,超過流/文件的長度會截斷,不足為實際值 流/文件實際長度
Expires 緩存過期時間,NOS未使用,格式是格林威治時間(GMT)
Cache-Control 指定該Object被下載時的網頁的緩存行為

下麵的源代碼實現了上傳文件時設置Http header:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 上傳文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="fileToUpload">上傳的文件</param>
public void putObject(string bucket, string key, string uploadFile)
{
    try
    {
        using (var fs = File.Open(fileToUpload, FileMode.Open))
        {
            var metadata = new ObjectMetadata
            {
                CacheControl = "no-cache",
                ContentDisposition = "abc.zip",
                ContentEncoding = "gzip",
            };
            //user metadata
            metadata.UserMetadata.Add("x-nos-meta-my-metaMyKey1", "MyValue1");
            metadata.UserMetadata.Add("x-nos-meta-my-metaMyKey2", "MyValue2");
            nosClient.PutObject(bucket, key, fs, metadata);

            Console.WriteLine("Put object succeeded");
        }
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 各種上傳方式(包括流式上傳、單塊上傳、分塊上傳)都可以設置元數據信息。流式上傳設置元數據的方式與單塊上傳相同,分塊上傳在構造ListMultipartUploadsRequest對象時傳入ObjectMetadata參數,如:ListMultipartUploadsRequest.ObjectMetadata;
 2. 文件的元信息可以通過NosClient.GetObjectMetadata獲取;
 3. user meta的名稱以”x-nos-meta-“開頭,例如設置為:’x-nos-meta-name’,讀取名字為x-nos-meta-name的參數即可;

上傳時校驗MD5

下麵的代碼實現了上傳時校驗MD5:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 上傳文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
/// <param name="fileToUpload">上傳的文件</param>
public void putObject(string bucket, string key, string uploadFile)
{
    try
    {
        string md5 = "";
        using (var fs = File.Open(fileToUpload, FileMode.Open))
        {
            md5 = NosUtil.GetMD5FromStream(fs);
            var metadata = new ObjectMetadata
            {
                ContentMD5 = md5
            };
            nosClient.PutObject(bucket, key, fs, metadata);

            Console.WriteLine("Put object succeeded");
        }
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
            ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 校驗MD5會有一定的性能損失;

文件下載

NOS C# SDK提供了豐富的文件下載接口,用戶可以通過以下方式從NOS獲取文件:

 1. 下載文件到內存
 2. 下載到本地文件
 3. 分段下載
 4. 條件下載

下載文件到內存

以下源代碼實現下載文件到內存中:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 下載文件到內存
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="bucket">對象名</param>
public void GetObject(string bucket, string key)
{
    try
    {
        var result = nosClient.GetObject(bucket, key);
        Console.WriteLine(result.Content);

        Console.WriteLine("Get object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

下載文件到本地文件

以下源代碼實現將NOS文件下載到本地文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 下載文件到本地
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="bucket">對象名</param>
/// <param name="bucket">下載到的本地文件</param>
public void GetObject(string bucket, string key, string fileToDownload)
{
    try
    {
        nosClient.GetObject(bucket, key, fileToDownload);

        Console.WriteLine("Get object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

指定範圍下載

如果存儲在NOS中的文件較大,並且您隻需要其中的一部分內容,您可以使用範圍下載,下載指定範圍的數據,如果指定的下載範圍為”0-100”,則返回結果為第0字節到第100字節的數據,返回的數據包含第100字節,即range=0-100,如果指定的範圍無效則下載整個文件,以下源代碼獲取range=0-100字節的內容:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 指定範圍下載
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="bucket">對象名</param>
/// <param name="bucket">下載到的本地文件</param>
public void GetObject(string bucketName, string key, string fileToDownload)
{
    try
    {
        var request = new GetObjectRequest(bucketName, key);
        request.Range = "bytes=0-100";
        var result = nosClient.GetObject(request,fileToDownload);

        Console.WriteLine("Get object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 下載內容也可以存儲到文件中
 2. 注意下載的區間為閉區間

條件下載

下載文件時,可以指定限定條件,滿足限定條件時下載,不滿足時報錯,不下載文件。可以使用的限定條件如下:

參數 說明 GetObjectRequest對應值
If-Modified-Since 如果指定的時間早於實際修改時間,則正常傳送。否則返回錯誤 GetObjectRequest.IfModifiedSince
// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 指定條件下載
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="bucket">對象名</param>
/// <param name="bucket">下載到的本地文件</param>
public void GetObject(string bucketName, string key, string fileToDownload)
{
    try
    {
        var request = new GetObjectRequest(bucketName, key);
        request.If-Modified-Since = "Fri, 13 Nov 2016 14:47:53 GMT";
        var result = nosClient.GetObject(request,fileToDownload);

        Console.WriteLine("Get object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 下載內容也可以存儲到文件中

文件管理

在NOS中,用戶可以通過一係列的接口管理桶(Bucket)中的文件(Object),比如ListObjects,DeleteObject,CopyObject,DoesObjectExist等。

列出桶中的文件

您可以使用NosClient.ListObjects列出存儲中間中的文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 列出指定存儲空間下的文件的摘要信息
/// </summary>
/// <param name="bucket">桶名</param>
public void ListObjects(string bucket)
{
    try
    {
        var keys = new List<string>();
        ObjectListing result = null;
        string nextMarker = string.Empty;
        do
        {
            var listObjectsRequest = new ListObjectsRequest(bucket)
            {
                    Marker = nextMarker,
                    MaxKeys = 100
            };
            result = nosClient.ListObjects(listObjectsRequest);

            foreach (var summary in result.ObjectSummarise)
            {
                    Console.WriteLine(summary.Key);
                    keys.Add(summary.Key);
            }

            nextMarker = result.NextMarker;
        } while (result.IsTruncated);

        Console.WriteLine("List objects of bucket:{0} succeeded ", bucket);
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

上述代碼中的ListObjectsRequest中的可選參數如下所示:

參數 說明
Delimiter 用於對Object名字進行分組的字符。所有名字包含指定的前綴且第一次出現delimiter字符之間的object作為一組元素。限製長度為10。
Prefix 限定返回的object key必須以prefix作為前綴。注意使用prefix查詢時,返回的key中仍會包含prefix
MaxKeys 限定此次返回object的最大數,如果不設定,默認為100
Marker 設定結果從marker之後按字母排序的第一個開始返回

Note:

 1. 上述表中的參數都是可選參數

判斷文件是否存在

您可以使用NosClient.DoesObjectExist判斷文件是否存在:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 判斷指定桶內是否存在指定文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
public void DoesObjectExist(string bucket, string key)
{
    try
    {
        var exist = nosClient.DoesObjectExist(bucket, key);
        Console.WriteLine("exist ? " + exist);
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

刪除單個文件

您可以使用NosClient.DeleteObject刪除單個需要刪除的文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 刪除單個文件
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
public void DeleteObject(string bucket, string key)
{
    try
    {
        nosClient.DeleteObject(bucket, key);
        Console.WriteLine("Delete object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

刪除多個文件

您可以使用NosClient.DeleteObjects批量刪除文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 刪除多個文件
/// </summary>
/// <param name="bucket">桶名</param>
public void DeleteObjects(string bucket)
{
    try
    {
        var keys = new List<string>();
        var listObjectsResult = nosClient.ListObjects(bucket);
        foreach (var summary in listObjectsResult.ObjectSummarise)
        {
            keys.Add(summary.Key);
            break;
        }
        var result = nosClient.DeleteObjects(bucket, keys, false);

        Console.WriteLine("Delete objects succeeded");

        if (result.Keys != null)
        {
            foreach (var deletedObject in result.Keys)
            {
                    Console.Write("\n[Deleted]: " + deletedObject.Key);
            }
        }
        if (result.Error != null)
        {
            foreach (var deleteError in result.Error)
            {
                    Console.Write("\n[Error]: " + deleteError.Key + "\t" + deleteError.Code + "\t" + deleteError.Message);
            }
        }
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

拷貝文件

您可以使用NosClient.CopyObject拷貝文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 拷貝文件
/// </summary>
/// <param name="sourceBucket">源桶名</param>
/// <param name="sourceKey">源對象名</param>
/// <param name="targetBucket">目標桶名</param>
/// <param name="targetKey">目標對象名</param>
public void CopyObject(string sourceBucket, string sourceKey, string targetBucket, string targetKey)
{
    try
    {
        var request = new CopyObjectRequest(sourceBucket, sourceKey, targetBucket, targetKey);
        nosClient.CopyObject(request);

        Console.WriteLine("Copy object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 支持跨桶的文件copy

移動文件

您可以使用NosClient.MoveObject移動文件:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 移動文件
/// </summary>
/// <param name="sourceBucket">源桶名</param>
/// <param name="sourceKey">源對象名</param>
/// <param name="targetBucket">目標桶名</param>
/// <param name="targetKey">目標對象名</param>
public void MoveObject(string sourceBucket, string sourceKey, string targetBucket, string targetKey)
{
    try
    {
        var request = new MoveObjectRequest(sourceBucket, sourceKey, targetBucket, targetKey);
        nosClient.MoveObject(request);

        Console.WriteLine("Move object succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

Attention:

 1. 暫時不支持跨桶的文件move

修改文件元信息

暫時不提供此類方法

獲取文件的文件元信息

您可以使用NosClient.GetObjectMetadata獲取對象的元數據信息:

// 初始化NosClient
var nosClient = new NosClient(endpoint, accessKeyId, accessKeySecret);

/// <summary>
/// 獲取文件的文件元信息
/// </summary>
/// <param name="bucket">桶名</param>
/// <param name="key">對象名</param>
public void GetObjectMetadata(string bucket, string key)
{
    try
    {
        var objectMetadata = nosClient.GetObjectMetadata(bucket, key);
        Console.WriteLine("Get Object Metadata succeeded");
    }
    catch (NosException ex)
    {
        Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
                ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
    }
    catch (Exception ex)
    {
        Console.WriteLine("Failed with error info: {0}", ex.Message);
    }
}

錯誤處理

異常處理

調用NosClient類的相關接口時,如果拋出異常,則表明操作失敗,否則操作成功。拋出異常時,方法返回的數據無效。NosClient類的接口異常時會拋出異常類 NosException 。

異常處理實例

錯誤處理代碼如下所示:

try
{
    nosClient.ListObjects(bucket);
}
catch (NosException ex)
{
    Console.WriteLine("Failed with HTTPStatus: {0}; \nErrorCode: {1}; \nErrorMessage: {2}; \nRequestID:{3}; \nResource:{4}",
            ex.StatusCode, ex.ErrorCode, ex.Message, ex.RequestId, ex.Resource);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with ErrorMessage: {0}", ex.Message);
}

NosException

NosException指包括兩類:

  • 客戶端異常,包括參數無效、文件不存在等錯誤。該類錯誤可以通過Exception.Message獲取錯誤信息。
  • 服務器端異常,指NOS返回的錯誤,比如無權限、文件不存在等。可以通過NosException.Message獲取錯誤信息。該類異常還包含以下信息:
 1. HTTPStatus: HTTP狀態碼,通過NosException.StatusCode獲取。
 2. ErrorCode: NOS返回給用戶的錯誤碼,通過NosException.ErrorCode獲取。
 3. ErrorMessage: NOS提供的錯誤描述,通過NosException.Message獲取。
 4. RequestId: 用於唯一標識該請求的UUID;當您無法解決問題時,可以憑這個RequestId來請求NOS開發工程師的幫助。通過NosException.RequestId獲取。
 5. Resource: NOS返回的包含了Bucket或Object的請求資源描述符。通過NosException.Resource獲取。

最後更新:2017-01-03 10:48:53

  上一篇:go 數據中心和域名
  下一篇:go 對象存儲 Node SDK