对象存储 .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