所有文档

          对象存储 BOS

          Object管理

          上传Object

          最简单的上传

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BOSClient.PutObject()方法。调用该方法时您需要提供Bucket名称、ObjectKey和Object的内容。可以通过如下四种方式上传Object:文件、数据流、二进制串和字符串的形式。
          • 示例代码
          public void PutObject(BosClient client, String bucketName, String objectKey, byte[] byte1, String string1)
          {
          
              // 获取指定文件
              FileInfo file = new FileInfo(<FilePath>);    //指定文件路径
          
              // 以文件形式上传Object
              PutObjectResponse putObjectFromFileResponse = client.PutObject(bucketName, objectKey, file);
          
              // 获取数据流
              Stream inputStream = file.OpenRead();
          
              // 以数据流形式上传Object
              PutObjectResponse putObjectResponseFromInputStream = client.PutObject(bucketName, objectKey, inputStream);
          
              // 以二进制串上传Object
              PutObjectResponse putObjectResponseFromByte = client.PutObject(bucketName, objectKey,Encoding.Default.GetBytes("sampledata"));
          
              // 以字符串上传Object
              PutObjectResponse putObjectResponseFromString = client.PutObject(bucketName, objectKey, "sampledata");
          
              // 打印ETag
              Console.WriteLine(putObjectFromFileResponse.ETAG);
          
          }

          说明:Object以文件的形式上传到BOS中,putObject函数支持不超过5GB的Object上传。在putObject请求处理成功后,BOS会在Header中返回Object的ETag作为文件标识。

          设定Object的Http Header

          BOS支持您在上传object时设定Http Header。

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BOSClient.PutObject()时候,您还可以传入一个ObjectMetadata对象,该对象可以设置自定义的Http Header。
          • 示例代码
          // 初始化上传输入流
          ObjectMetadata meta = new ObjectMetadata();
          
          // 设置ContentLength大小
          meta.ContentLength = <Length>;
          
          // 设置ContentType
          meta.ContentType = "application/json";
          
          client.PutObject(bucketName, objectKey, <SampleData>, meta);

          用户自定义元数据

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BOSClient.PutObject()时候,您还可以传入一个ObjectMetadata对象,该对象支持用户自定义元数据来对Object进行描述。
          • 示例代码
          // 设置自定义元数据name的值为my-data
          meta.UserMetadata["name"] = "my-data";
          
          // 上传Object
          client.PutObject(bucketName, objectKey, <SampleData>, meta);
          > **说明:**在上面代码中,用户自定义了一个名字为”name”,值为”my-data”的元数据。当用户下载此Object的时候,此元数据也可以一并得到。一个Object可以有多个类似的参数,但所有的User Meta总大小不能超过2KB。

          完整示例

          下面示例代码演示了简单上传Object、设定Object的Http Header和用户自定义元数据的完整过程:

          using System;
          using System.Collections.Generic;
          using System.IO;
          using System.Linq;
          using System.Text;
          using BaiduBce;
          using BaiduBce.Auth;
          using BaiduBce.Services.Bos;
          using BaiduBce.Services.Bos.Model;
          
          namespace DotnetSample
          {
              internal class PutObjectSample
              {
                  private static void Main(string[] args)
                  {
                      BosClient client = GenerateBosClient();
                      const string bucketName = <BucketName>;        //您的Bucket名称
                      const string objectNameFile = <ObjectNameFile>;  //文件形式上传的Object名称
                      const string objectNameStream = <ObjectNameStream>; //数据流形式上传的Object名称
                      const string objectNameString = <ObjectNameString>; //字符串形式上传的Object名称
                      const string objectNameByte = <ObjectNameByte>; //二进制形式上传的Object名称
          
                      // 新建一个Bucket
                      client.CreateBucket(bucketName); //指定Bucket名称
          
                      // 设置待上传的文件名
                      const string fileName = "d:\\sample.txt";
          
                      // 以文件形式上传Object
                      PutObjectResponse putObjectFromFileResponse = client.PutObject(bucketName, objectNameFile,
                          new FileInfo(fileName));
          
                      // 以数据流形式上传Object
                      PutObjectResponse putObjectResponseFromInputStream = client.PutObject(bucketName, objectNameStream,
                          new FileInfo(fileName).OpenRead());
          
                      // 以二进制串上传Object
                      PutObjectResponse putObjectResponseFromByte = client.PutObject(bucketName, objectNameByte,
                          Encoding.Default.GetBytes("sampledata"));
          
                      // 以字符串上传Object
                      PutObjectResponse putObjectResponseFromString = client.PutObject(bucketName, objectNameString,
                          "sampledata");
          
                      // 打印四种方式的ETag。示例中,文件方式和stream方式的ETag相等,string方式和byte方式的ETag相等
                      Console.WriteLine(putObjectFromFileResponse.ETAG);
                      Console.WriteLine(putObjectResponseFromInputStream.ETAG);
                      Console.WriteLine(putObjectResponseFromByte.ETAG);
                      Console.WriteLine(putObjectResponseFromString.ETAG);
          
                      // 上传Object并设置自定义参数
                      ObjectMetadata meta = new ObjectMetadata();
                      // 设置ContentLength大小
                      meta.ContentLength = 10;
                      // 设置ContentType
                      meta.ContentType = "application/json";
                      // 设置自定义元数据name的值为my-data
                      meta.UserMetadata["name"] = "my-data";
                      // 上传Object并打印ETag
                      putObjectResponseFromString = client.PutObject(bucketName, objectNameString, "sampledata", meta);
                      Console.WriteLine(putObjectResponseFromString.ETAG);
                  }
          
                  private static BosClient GenerateBosClient()
                  {
                      const string accessKeyId = <AccessKeyID>; // 您的Access Key ID
                      const string secretAccessKey = <SecretAccessKey>; // 您的Secret Access Key
                      const string endpoint = <EndPoint>; // 指定BOS服务域名
          
                      // 初始化一个BosClient
                      BceClientConfiguration config = new BceClientConfiguration();
                      config.Credentials = new DefaultBceCredentials(accessKeyId, secretAccessKey);
                      config.Endpoint = endpoint;
          
                      return new BosClient(config);
                  }
              }
          }

          查看Bucket中的Object

          简单查询

          查看Bucket中Object列表。

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BOSClient.ListObjects()方法。调用该方法时你需要提供Bucket名称。
          • 示例代码

            public void ListObjects(BosClient client, string bucketName)
            {
            
                // 获取指定Bucket下的所有Object信息
                ListObjectsResponse listObjectsResponse = client.ListObjects(bucketName);
            
                // 遍历所有Object
                foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
                {
                    Console.WriteLine("ObjectKey: " + objectSummary.Key);
                }
            
            }

            说明: listObjects( )方法返回ListObjectsResponse对象,ListObjectsResponse对象包含了此次listObject请求的返回结果。用户可以通过ListObjectsResponse中的getContents方法获取所有Object的描述信息。

            • 默认情况下,如果Bucket中的Object数量大于1000,则只会返回1000个Object,并且返回结果中IsTruncated值为True,并返回NextMarker做为下次读取的起点。
            • 若想获取更多的Object,可以使用Marker参数分次读取,请参考扩展查询
          • 完整示例

            请参考完整示例

          扩展查询

          用户可以通过设置ListObjectsRequest参数来完成更多扩展查询操作设置。ListObjectsRequest中可以设置的扩展参数如下:

          参数名称 说明 默认值
          MaxKeys 设定此次返回Object的最大个数,不可超过1000。 1000
          Prefix 设定objectKey的前缀,前缀是指objectKey包含并以Prefix的值作为开始。
          通常与Delimiter配合在查询模拟文件夹中使用。
          -
          Delimiter 是一个分隔符,用来对objectKey进行分层。
          通常与Prefix配合在查询模拟文件夹中使用。
          从Prefix开始到第一次出现Delimiter字符之间的objectKey称为:CommonPrefixes。
          -
          Marker 是一个字符串,用来设定返回结果的起始位置。
          设定Marker值之后,返回的Object会从Marker值之后按字母排序开始返回。
          -
          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 您也可以构造一个ListObjectsRequest来调用ListObjects(),ListObjectsRequest等方法,实现更多的扩展查询操作。
          • 示例代码

            // 构造ListObjectsRequest请求
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest() {BucketName = bucketName};
            
            // 设置参数
            listObjectsRequest.Delimiter=<Delimiter>;
            listObjectsRequest.Marker=<Marker>;
            
            ListObjectsResponse listObjectsResponse = client.ListObjects(listObjectsRequest);

            说明:

            上面代码中调用了 listObjects 中的一个重载方法,通过传入 ListObjectsRequest 来完成请求。

          • 完整示例

            请参考完整示例

          查询模拟文件夹

          由于BOS本身是一个(<Key>,<Value>)的存储系统,所以原则上并不会存在“文件夹”的概念,但您可以通过 DelimiterPrefix 参数的配合进行文件夹功能模拟。

          假设Bucket中有5个文件:bos.jpg,fun/,fun/test.jpg,fun/movie/001.avi,fun/movie/007.avi,可以把 “/” 符号作为分隔符模拟文件夹。

          递归列出模拟文件夹下所有文件

          可以通过设置 Prefix 参数来获取某个目录下所有的文件:

          // 构造ListObjectsRequest请求
          ListObjectsRequest listObjectsRequest = new ListObjectsRequest() {BucketName = bucketName};
          
          // 递归列出fun目录下的所有文件
          listObjectsRequest.Prefix = "fun/";
          
          // List Objects
          ListObjectsResponse listObjectsResponse = client.ListObjects(listObjectsRequest);
          
          // 遍历所有Object
          Console.WriteLine("Objects:");
          foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
          {
              Console.WriteLine("ObjectKey: " + objectSummary.Key);
          }

          输出:

          Objects:
          fun/
          fun/movie/001.avi
          fun/movie/007.avi
          fun/test.jpg

          查看模拟文件夹下的文件和子文件夹

          PrefixDelimiter 结合的情况下,可以列出模拟文件夹下的文件和子文件夹:

          // 构造ListObjectsRequest请求
          ListObjectsRequest listObjectsRequest = new ListObjectsRequest() {BucketName = bucketName};
          
          // "/" 为文件夹的分隔符
          listObjectsRequest.Delimiter = "/";
          
          // 列出fun目录下的所有文件和文件夹
          listObjectsRequest.Prefix = "fun/";
          
          // List Objects
          ListObjectsResponse listObjectsResponse = client.ListObjects(listObjectsRequest);
          
          // 遍历所有Object,相当于获取fun目录下的所有文件
          Console.WriteLine("Objects:");
          foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
          {
              Console.WriteLine("ObjectKey: " + objectSummary.Key);
          }
          
          // 遍历所有CommonPrefix,相当于获取fun目录下的所有文件夹
          Console.WriteLine("\nCommonPrefixs:");
          foreach (ObjectPrefix objectPrefix in listObjectsResponse.CommonPrefixes)
          {
              Console.WriteLine(objectPrefix.Prefix);
          }

          输出:

          Objects:
          fun/
          fun/test.jpg
          
          CommonPrefixs:
          fun/movie/

          说明:

          返回的结果中, Objects 的列表中给出的是fun文件夹下的文件。而 CommonPrefixs 的列表中给出的是fun文件夹下的所有子文件夹。可以看出 fun/movie/001.avifun/movie/007.avi 两个文件并没有被列出来,因为它们属于 fun 文件夹下的 movie 子文件夹下的文件。

          完整示例

          下面示例代码演示了Object的简单查询、使用nextmarker分次查询、扩展查询、查询模拟文件夹的完整过程:

          using System;
          using System.Collections.Generic;
          using System.Linq;
          using System.Text;
          using BaiduBce;
          using BaiduBce.Auth;
          using BaiduBce.Services.Bos;
          using BaiduBce.Services.Bos.Model;
          
          namespace DotnetSample
          {
              internal class ListObjectsSample
              {
                  private static void Main(string[] args)
                  {
                      BosClient client = GenerateBosClient();
                      const string bucketName = <BucketName>;     //您的Bucket名称
          
                      // 新建一个Bucket
                      client.CreateBucket(bucketName); 
          
                      // 创建bos.jpg,fun/,fun/test.jpg,fun/movie/001.avi,fun/movie/007.avi五个文件
                      client.PutObject(bucketName, "bos.jpg", "sampledata");
                      client.PutObject(bucketName, "fun/", "sampledata");
                      client.PutObject(bucketName, "fun/test.jpg", "sampledata");
                      client.PutObject(bucketName, "fun/movie/001.avi", "sampledata");
                      client.PutObject(bucketName, "fun/movie/007.avi", "sampledata");
          
                      // 构造ListObjectsRequest请求
                      ListObjectsRequest listObjectsRequest = new ListObjectsRequest() { BucketName = bucketName };
          
                      // 1. 简单查询,列出Bucket下所有文件
                      ListObjectsResponse listObjectsResponse = client.ListObjects(listObjectsRequest);
          
                      // 输出:    
                      // Objects:
                      // bos.jpg
                      // fun/
                      // fun/movie/001.avi
                      // fun/movie/007.avi
                      // fun/test.jpg
          
                      Console.WriteLine("Objects:");
                      foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
                      {
                          Console.WriteLine("ObjectKey: " + objectSummary.Key);
                      }
          
                      // 2. 使用NextMarker分次列出所有文件
                      listObjectsRequest.MaxKeys = 2;
                      listObjectsResponse = client.ListObjects(listObjectsRequest);
          
                      // 输出:    
                      // Objects:
                      // bos.jpg
                      // fun/
                      // fun/movie/001.avi
                      // fun/movie/007.avi
                      // fun/test.jpg
                      Console.WriteLine("Objects:");
                      while (listObjectsResponse.IsTruncated)
                      {
                          foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
                          {
                              Console.WriteLine("ObjectKey: " + objectSummary.Key);
                          }
                          listObjectsResponse = client.ListNextBatchOfObjects(listObjectsResponse);
                      }
                      foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
                      {
                          Console.WriteLine("ObjectKey: " + objectSummary.Key);
                      }
          
                      // 3. 递归列出“fun/”下所有文件和子文件夹
                      listObjectsRequest.Prefix = "fun/";
                      listObjectsResponse = client.ListObjects(listObjectsRequest);
          
                      // 输出:    
                      // Objects:
                      // fun/
                      // fun/movie/001.avi
                      // fun/movie/007.avi
                      // fun/test.jpg
          
                      Console.WriteLine("Objects:");
                      foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
                      {
                          Console.WriteLine("ObjectKey: " + objectSummary.Key);
                      }
          
                      // 4. 列出“fun”下的文件和子文件夹
                      listObjectsRequest.Delimiter = "/";
                      listObjectsResponse = client.ListObjects(listObjectsRequest);
          
                      // 输出:
                      // Objects:
                      // fun/
                      // fun/test.jpg
          
                      Console.WriteLine("Objects:");
                      foreach (BosObjectSummary objectSummary in listObjectsResponse.Contents)
                      {
                          Console.WriteLine("ObjectKey: " + objectSummary.Key);
                      }
          
                      // 遍历所有CommonPrefix,相当于获取fun目录下的所有子文件夹
                      // 输出:    
                      // CommonPrefixs:
                      // fun/movie
          
                      Console.WriteLine("\nCommonPrefixs:");
                      foreach (ObjectPrefix objectPrefix in listObjectsResponse.CommonPrefixes)
                      {
                          Console.WriteLine(objectPrefix.Prefix);
                      }
                  }
          
                  private static BosClient GenerateBosClient()
                  {
                      const string accessKeyId = <AccessKeyID>; // 您的Access Key ID
                      const string secretAccessKey = <SecretAccessKey>; // 您的Secret Access Key
                      const string endpoint = <EndPoint>; // 指定BOS服务域名
          
                      // 初始化一个BosClient
                      BceClientConfiguration config = new BceClientConfiguration();
                      config.Credentials = new DefaultBceCredentials(accessKeyId, secretAccessKey);
                      config.Endpoint = endpoint;
          
                      return new BosClient(config);
                  }
              }
          }

          获取Object

          简单的获取Object

          • 基本流程

            1. 创建BOSClient类的实例。
            2. 执行BOSClient.GetObject()方法,会返回指定的BosObject。
            3. 将BosObject读到流中,然后对流进行操作。
          • 示例代码

            public void GetObject(BosClient client, String bucketName, String objectKey)
            {
            
                // 获取Object,返回结果为BosObject对象
                BosObject bosObject = client.GetObject(bucketName, objectKey);
            
                // 获取ObjectMeta
                ObjectMetadata meta = bosObject.ObjectMetadata;
            
                // 获取Object的输入流
                Stream objectContent = bosObject.ObjectContent;
            
                // 处理Object
                ...
            
                // 关闭流
                objectContent.Close();
            }

            注意:

            • BosObject中包含了Object的各种信息,包含Object所在的Bucket、Object的名称、MetaData以及一个输入流,
            • 用户可以通过操作输入流将Object的内容读取到文件或者内存中。
            • ObjectMetadata中包含了Object上传时定义的ETag,Http Header以及自定义的元数据。
            • 通过BosObject的getObjectContent()方法,还可以获取返回Object的输入流,用户可以读取这个输入流来对Object的内容进行操作。
          • 完整示例

            请参考完整示例

          通过GetObjectRequest获取Object

          为了实现更多的功能,可以通过使用GetObjectRequest来获取Object。

          • 基本流程

            1. 创建GetObjectRequest类的实例。
            2. 对GetObjectRequest执行setRange( ),获取Object中所需的字节数据。
            3. 执行GetObject( )操作。
          • 示例代码

            // 新建GetObjectRequest
             GetObjectRequest getObjectRequest = new GetObjectRequest() {BucketName = bucketName, Key = objectKey};
            
            // 获取0~100字节范围内的数据
            getObjectRequest.SetRange(0, 100);
            
            // 获取Object,返回结果为BosObject对象
            BosObject bosObject = client.GetObject(getObjectRequest);

            说明:通过getObjectRequest的setRange( )方法可以设置返回Object的范围。用户可以用此功能实现文件的分段下载和断点续传。

          • 完整示例

            请参考完整示例

          直接下载Object到指定路径

          用户可以通过如下代码直接将Object下载到指定路径。

          • 基本流程

            1. 创建GetObjectRequest类的实例。
            2. 执行client.getObject( )操作。
            3. Object可以直接下载到指定路径。
          • 示例代码

            // 新建GetObjectRequest
            GetObjectRequest getObjectRequest = new GetObjectRequest() {BucketName = bucketName, Key = objectKey};
            
            // 下载Object到文件
            ObjectMetadata objectMetadata = client.GetObject(getObjectRequest, new FileInfo("d:\\sample.txt"));

            说明:当使用上面方法将Object直接下载到指定路径时,方法会返回ObjectMetadata对象。

          • 完整示例

            请参考完整示例

          只获取ObjectMetadata

          通过 getObjectMetadata() 方法可以只获取ObjectMetadata而不获取Object的实体。

          • 示例代码

            ObjectMetadata objectMetadata = client.GetObjectMetadata(bucketName, objectKey);
          • 完整示例

            请参考完整示例

          获取Object的URL

          您可以通过如下代码获取指定Object的URL,该功能通常用于您将Object的URL临时分享给其他用户的场景。

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BosClient.GeneratePresignedUrl()方法,在调用该方法时您需要提供Bucket名称,object名称,过期时间等参数。
            3. 返回一个Object的URL。
          • 示例代码

            public string GeneratePresignedUrl(BosClient client, string bucketName, string objectKey,
                      int expirationInSeconds)
            {
               //指定用户需要获取的Object所在的Bucket名称、该Object名称、时间戳、URL的有效时长
               Uri url = client.GeneratePresignedUrl(bucketName, objectKey, expirationInSeconds);             
               return url.AbsoluteUri;
            }

            说明:ExpirationInSeconds为指定的URL有效时长,时间从当前时间算起,为可选参数,不配置时系统默认值为1800秒。如果要设置为永久不失效的时间,可以将ExpirationInSeconds参数设置为 -1,不可设置为其他负数。

          • 完整示例

            请参考完整示例

          完整示例

          下面示例代码演示了简单获取Object、通过GetObjectRequest获取Object、直接下载Object到指定路径、只获取ObjectMetadata以及获取Object的URL的完整过程:

          using System;
          using System.Collections.Generic;
          using System.IO;
          using System.Linq;
          using System.Text;
          using BaiduBce;
          using BaiduBce.Auth;
          using BaiduBce.Services.Bos;
          using BaiduBce.Services.Bos.Model;
          
          namespace DotnetSample
          {
              internal class GetObjectsSample
              {
                  private static void Main(string[] args)
                  {
                      BosClient client = GenerateBosClient();
                      const string bucketName = <BucketName>; //您的Bucket名称
          
                      // 初始化,创建Bucket和Object
                      client.CreateBucket(bucketName); 
                      string objectName = <ObjectKey>;
                      client.PutObject(bucketName, objectName, <SampleData>);
          
                      // 获取BosObject对象并通过BosObject的输入流获取内容
                      BosObject bosObject = client.GetObject(bucketName, objectName);
                      Stream objectContent = bosObject.ObjectContent;
                      string content = new StreamReader(objectContent).ReadToEnd();
                      Console.WriteLine(content); // 您传入的<SampleData>
          
                      // 通过GetObjectRequest只获取部分数据
                      GetObjectRequest getObjectRequest = new GetObjectRequest() {BucketName = bucketName, Key = objectName};
                      getObjectRequest.SetRange(0, 5);
                      bosObject = client.GetObject(getObjectRequest);
                      objectContent = bosObject.ObjectContent;
                      content = new StreamReader(objectContent).ReadToEnd();
                      Console.WriteLine(content); // 您传入的<SampleData>
          
                      // 直接通过GetObjectContent获取byte[]内容
                      byte[] bytes = client.GetObjectContent(bucketName, objectName);
                      content = Encoding.Default.GetString(bytes);
                      Console.WriteLine(content); // 您传入的<SampleData>
          
                      // 将Object内容下载到文件
                      FileInfo fileInfo = new FileInfo("my file path and name");
                      client.GetObject(bucketName, objectName,fileInfo );
                      content = File.ReadAllText(fileInfo.FullName);
                      Console.WriteLine(content); // 您传入的<SampleData>
          
                      // 只获取object的meta,不获取内容
                      ObjectMetadata objectMetadata = client.GetObjectMetadata(bucketName, objectName);
                      Console.WriteLine(objectMetadata.ContentLength); 
          
                      Console.ReadKey();
          
                      // 生成url,并通过该url直接下载和打印对象内容
                      string url = client.GeneratePresignedUrl(bucketName, objectName, 60).AbsoluteUri;
                      using (WebClient webClient = new WebClient())
                      {
                          using (Stream stream = webClient.OpenRead(url))
                          using (StreamReader streamReader = new StreamReader(stream))
                          {
                              string response = streamReader.ReadToEnd();
                              Console.WriteLine(response);  // 您传入的<SampleData>
                          }
                      }
                  }
          
                  private static BosClient GenerateBosClient()
                  {
                      const string accessKeyId = <AccessKeyID>; // 您的Access Key ID
                      const string secretAccessKey = <SecretAccessKey>; // 您的Secret Access Key
                      const string endpoint = <EndPoint>; // 指定BOS服务域名
          
                      // 初始化一个BosClient
                      BceClientConfiguration config = new BceClientConfiguration();
                      config.Credentials = new DefaultBceCredentials(accessKeyId, secretAccessKey);
                      config.Endpoint = endpoint;
          
                      return new BosClient(config);
                  }
              }
          }

          删除Object

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BosClient.DeleteObject()方法。在调用该方法时你需要提供Bucket名称,Object名称等参数。
          • 示例代码

            public void DeleteObject(BosClient client, string bucketName, string objectKey)
            {
            // 删除Object
            client.DeleteObject(bucketName, objectKey); 
            }
          • 完整示例

            using System;
            using System.Collections.Generic;
            using System.IO;
            using System.Linq;
            using System.Net;
            using System.Text;
            using BaiduBce;
            using BaiduBce.Auth;
            using BaiduBce.Services.Bos;
            using BaiduBce.Services.Bos.Model;
            
            namespace DotnetSample
            {
                internal class DeleteObjectSample
                {
                    private static void Main(string[] args)
                    {
                        BosClient client = GenerateBosClient();
                        const string bucketName = <BucketName>;     //指定Bucket名称
            
                        // 初始化:创建示例Bucket和Object
                        client.CreateBucket(bucketName); 
                        string objectName = <ObjectKey>;
                        client.PutObject(bucketName, objectName, <Sampledata>);
            
                        // 删除Object
                        client.DeleteObject(bucketName, objectName);
                    }
            
                    private static BosClient GenerateBosClient()
                    {
                        const string accessKeyId = <AccessKeyID>; // 您的Access Key ID
                        const string secretAccessKey = <SecretAccessKey>; // 您的Secret Access Key
                        const string endpoint = <EndPoint>; // 指定BOS服务域名
            
                        // 初始化一个BosClient
                        BceClientConfiguration config = new BceClientConfiguration();
                        config.Credentials = new DefaultBceCredentials(accessKeyId, secretAccessKey);
                        config.Endpoint = endpoint;
            
                        return new BosClient(config);
                    }
                }
            }

          拷贝Object

          简单拷贝Object

          • 基本流程

            1. 创建BOSClient 类的实例。
            2. 执行BOSClient.copyObject( )方法。
          • 示例代码

            public void CopyObject(BosClient client, String srcBucketName, String srcKey, String destBucketName,
            String destKey)
            {
               // 拷贝Object
               CopyObjectResponse copyObjectResponse = client.CopyObject(srcBucketName, srcKey, destBucketName, destKey);
            
               // 打印结果
               Console.WriteLine("ETag: " + copyObjectResponse.ETag + " LastModified: " + copyObjectResponse.LastModified);
            }

            说明:copyObject 方法返回一个 CopyObjectResponse 对象,该对象中包含了新Object的ETag和修改时间。

          • 完整示例

            请参考完整示例

          通过CopyObjectRequest拷贝Object

          您也可以通过 CopyObjectRequest 实现Object的拷贝。该功能一般用于如下场景:

          • Copy一个Object但重新设置meta。
          • 重置某个现有Object的meta(把Src和Des设置为同一个Object)。
          • 基本流程

            1. 创建CopyObjectRequest类的实例,传入<SrcBucketName>, <SrcKey>, <DestBucketName>, <DestKey>参数。
            2. 创建ObjectMetadata类的实例。
          • 示例代码

            // 初始化BosClient
            BosClient client = ...;
            
            // 创建CopyObjectRequest对象
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest()
            {
                SourceBucketName = srcBucketName,
                SourceKey = srcKey,
                BucketName = destBucketName,
                Key = destKey
            };
            
            // 设置新的Metadata
            Dictionary<String, String> userMetadata = new Dictionary<String, String>();
            userMetadata["usermetakey"] = "usermetavalue";
            ObjectMetadata objectMetadata = new ObjectMetadata()
            {
                UserMetadata = userMetadata
            };
            copyObjectRequest.NewObjectMetadata = objectMetadata;
            
            // 复制Object并打印新的ETag
            CopyObjectResponse copyObjectResponse = client.CopyObject(copyObjectRequest);
            Console.WriteLine("ETag: " + copyObjectResponse.ETag + " LastModified: " + copyObjectResponse.LastModified);

            说明:CopyObjectRequest 允许用户修改目的Object的ObjectMeta,同时也提供 MatchingETagConstraints 参数的设定。

          • 完整示例

            请参考完整示例

          完整示例

          下面示例代码演示了简单拷贝Object和通过CopyObjectRequest拷贝Object的完整过程:

          using System;
          using System.Collections.Generic;
          using System.IO;
          using System.Linq;
          using System.Net;
          using System.Text;
          using BaiduBce;
          using BaiduBce.Auth;
          using BaiduBce.Services.Bos;
          using BaiduBce.Services.Bos.Model;
          
          namespace DotnetSample
          {
              internal class CopyObjectSample
              {
                  private static void Main(string[] args)
                  {
                      BosClient client = GenerateBosClient();
                      const string bucketName = <SrcBucketName>; 
          
                      // 初始化,创建示例Bucket和Object
                      client.CreateBucket(bucketName); 
                      string objectName = <SrcObjectKey>;
                      client.PutObject(bucketName, objectName, <SrcSampleData>);
          
                      // 普通拷贝并打印结果
                      string newObjectName = <DesObjectKey>;
                      CopyObjectResponse copyObjectResponse = client.CopyObject(bucketName, objectName, bucketName,
                          newObjectName);
          
                      Console.WriteLine(Encoding.Default.GetString(client.GetObjectContent(bucketName, newObjectName)));
          
                      // 拷贝并设置新的meta
                      newObjectName = <DesObjectKey>;
                      CopyObjectRequest copyObjectRequest = new CopyObjectRequest()
                      {
                          SourceBucketName = bucketName,
                          SourceKey = objectName,
                          BucketName = bucketName,
                          Key = newObjectName
                      };
                      Dictionary<String, String> userMetadata = new Dictionary<String, String>();
                      userMetadata["usermetakey"] = "usermetavalue";
                      ObjectMetadata objectMetadata = new ObjectMetadata()
                      {
                          UserMetadata = userMetadata
                      };
                      copyObjectRequest.NewObjectMetadata = objectMetadata;
                      client.CopyObject(copyObjectRequest);
                      // usermetavalue
                      Console.WriteLine(client.GetObjectMetadata(bucketName, newObjectName).UserMetadata["usermetakey"]);
                  }
          
                  private static BosClient GenerateBosClient()
                  {
                      const string accessKeyId = <AccessKeyID>; // 您的Access Key ID
                      const string secretAccessKey = <SecretAccessKey>; // 您的Secret Access Key
                      const string endpoint = <EndPoint>; // 指定BOS服务域名
          
                      // 初始化一个BosClient
                      BceClientConfiguration config = new BceClientConfiguration();
                      config.Credentials = new DefaultBceCredentials(accessKeyId, secretAccessKey);
                      config.Endpoint = endpoint;
          
                      return new BosClient(config);
                  }
              }
          }

          Object的分块上传

          除了通过putObject()方法上传文件到BOS以外,BOS还提供了另外一种上传模式:分块上传(Multipart Upload)。用户可以在如下的应用场景内(但不仅限于此),使用分块上传模式,如:

          • 需要支持断点上传。
          • 上传超过5GB大小的文件。
          • 网络条件较差,和BOS的服务器之间的连接经常断开。
          • 需要流式地上传文件。
          • 上传文件之前,无法确定上传文件的大小。

          分块完成Multipart Upload

          假设有一个文件,本地路径为 d:\\sample.txt ,由于文件比较大,将其分块传输到BOS中。

          • 基本流程

            1. 创建一个BOSClient类的实例。
            2. 调用BosClient.InitiateMultipartUpload()方法。在调用该方法时您需要提供Bucket名称和Object名称,该方法会返回一个UploadId,在后面的步骤中需要用到该Id。
            3. 多次调用调用BosClient.UploadPart方法将文件分块多次上传。调用该方法时您需要提供Bucket名称,Object名称,UploadId,分块序号,分块大小,分块内容等参数,每次调用该方法都会返回本次分块的序号和ETag,在后面的步骤中会用到。
            4. 调用BosClient.CompleteMultipartUpload()方法完成本次分块上传。调用该方法您需要提供Bucket名称,Object名称,UploadId以及每个分块的序号和ETag。
            5. 上传过程中可以通过BosClient.ListParts()方法获取指定UploadId中已经上传的所有块;还可以通过BosClient.ListMultipartUploads()方法获取指定Bucket中所有未完成的UploadId。

          初始化Multipart Upload

          使用 InitiateMultipartUpload 方法来初始化一个分块上传事件:

          • 示例代码

            // 开始Multipart Upload
            InitiateMultipartUploadRequest initiateMultipartUploadRequest =
                     new InitiateMultipartUploadRequest() {BucketName = bucketName, Key = objectKey};
            InitiateMultipartUploadResponse initiateMultipartUploadResponse =
                     client.InitiateMultipartUpload(initiateMultipartUploadRequest);
            
            // 打印UploadId
            Console.WriteLine("UploadId: " + initiateMultipartUploadResponse.UploadId);

            说明:initiateMultipartUpload 的返回结果中含有 UploadId ,它是区分分块上传事件的唯一标识,在后面的操作中,我们将用到它。

          上传分块

          把文件分块上传。

          • 示例代码

            // 设置每块为 5Mb
            long partSize = 1024 * 1024 * 5L;
            
            FileInfo partFile = new FileInfo("my file");
            
            // 计算分块数目
            int partCount = (int) (partFile.Length / partSize);
            if (partFile.Length % partSize != 0)
            {
               partCount++;
            }
            
            // 新建一个List保存每个分块上传后的ETag和PartNumber
            List<PartETag> partETags = new List<PartETag>();
            
            for (int i = 0; i < partCount; i++)
            {
               // 获取文件流
               Stream stream = partFile.OpenRead();
            
               // 跳到每个分块的开头
               long skipBytes = partSize * i;
               stream.Seek(skipBytes, SeekOrigin.Begin);
            
               // 计算每个分块的大小
               long size = Math.Min(partSize, partFile.Length - skipBytes);
            
               // 创建UploadPartRequest,上传分块
               uploadPartRequest uploadPartRequest = new UploadPartRequest();
               uploadPartRequest.BucketName = bucketName;
               uploadPartRequest.Key = objectKey;
               uploadPartRequest.UploadId = initiateMultipartUploadResponse.UploadId;
               uploadPartRequest.InputStream = stream;
               uploadPartRequest.PartSize = size;
               uploadPartRequest.PartNumber = i + 1;
               UploadPartResponse uploadPartResponse = client.UploadPart(uploadPartRequest);
            
               // 将返回的PartETag保存到List中。
               partETags.Add(new PartETag()
               {
                  ETag = uploadPartResponse.ETag,
                  PartNumber = uploadPartResponse.PartNumber
                });
            
               // 关闭文件
               stream.Close();
               }

            注意:

            上面代码的核心是调用 UploadPart 方法来上传每一个分块,但是要注意以下几点:

            • 分块上传方法要求除最后一个Part以外,其他的Part大小都要大于等于5MB。但是Upload Part接口并不会检查上传Part的大小;只有当Complete Multipart Upload的时候才会校验。
            • 为了保证数据在网络传输过程中不出现错误,建议您在UploadPart后,使用每个分块BOS返回的Content-MD5值分别验证已上传分块数据的正确性。当所有分块数据合成一个Object后,不再含MD5值。
            • Part号码的范围是1~10000。如果超出这个范围,BOS将返回InvalidArgument的错误码。
            • 每次上传Part时都要把流定位到此次上传块开头所对应的位置。
            • 每次上传Part之后,BOS的返回结果会包含一个 PartETag 对象,它是上传块的ETag与块编号(PartNumber)的组合,在后续完成分块上传的步骤中会用到它,因此需要将其保存起来。一般来讲这些 PartETag 对象将被保存到List中。

          完成分块上传

          • 示例代码

            CompleteMultipartUploadRequest completeMultipartUploadRequest =
            new CompleteMultipartUploadRequest()
            {
               BucketName = bucketName,
               Key = objectKey,
               UploadId = initiateMultipartUploadResponse.UploadId,
               PartETags = partETags
            };
            
            // 完成分块上传
            CompleteMultipartUploadResponse completeMultipartUploadResponse =
            client.CompleteMultipartUpload(completeMultipartUploadRequest);
            
            // 打印Object的ETag
            Console.WriteLine(completeMultipartUploadResponse.ETag);

            说明:上面代码中的 partETags 是第二部中保存的partETag的列表,BOS收到用户提交的Part列表后,会逐一验证每个数据Part的有效性。当所有的数据Part验证通过后,BOS将把这些数据part组合成一个完整的Object。

          取消分块上传事件

          用户可以使用abortMultipartUpload方法取消分块上传。

          • 示例代码

            AbortMultipartUploadRequest abortMultipartUploadRequest = new AbortMultipartUploadRequest()
            {
                BucketName = bucketName,
                Key = objectKey,
                UploadId = initiateMultipartUploadResponse.UploadId,
            };
            
            // 取消分块上传
            client.AbortMultipartUpload(abortMultipartUploadRequest);	

          获取未完成的分块上传事件

          用户可以使用 ListMultipartUploads 方法获取Bucket内未完成的分块上传事件。

          • 示例代码

            ListMultipartUploadsRequest listMultipartUploadsRequest =
                 new ListMultipartUploadsRequest() {BucketName = bucketName};
            
            // 获取Bucket内所有上传事件
            ListMultipartUploadsResponse listMultipartUploadsResponse =
                 client.ListMultipartUploads(listMultipartUploadsRequest);
            
            // 遍历所有上传事件
            foreach (MultipartUploadSummary multipartUpload in listMultipartUploadsResponse.Uploads)
            {
               Console.WriteLine("Key: " + multipartUpload.Key + " UploadId: " + multipartUpload.UploadId);
            }

            注意:

            • 默认情况下,如果Bucket中的分块上传事件的数目大于1000,则只会返回1000个,并且返回结果中IsTruncated的值为True,同时返回NextKeyMarker作为下次读取的起点。
            • 若想获取更多分块上传事件,可以使用KeyMarker参数分次读取。

          获取所有已上传的块信息

          用户可以使用 ListParts 方法获取某个上传事件中所有已上传的块。

          • 示例代码

            ListPartsRequest listPartsRequest = new ListPartsRequest()
            {
                BucketName = bucketName,
                Key = objectKey,
                UploadId = initiateMultipartUploadResponse.UploadId,
            };
            
            // 获取上传的所有Part信息
            ListPartsResponse listPartsResponse = client.ListParts(listPartsRequest);
            
            // 遍历所有Part
            foreach (PartSummary part in listPartsResponse.Parts)
            {
                 Console.WriteLine("PartNumber: " + part.PartNumber + " ETag: " + part.ETag);
            }

            注意:

            • 默认情况下,如果Bucket中的分块上传事件的数目大于1000,则只会返回1000个part,并且返回结果中IsTruncated的值为True,同时返回NextPartNumberMarker作为下次读取的起点。
            • 若想获取更多已上传的分块信息,可以使用PartNumberMarker参数分次读取。

          完整示例

          下面示例代码演示了分块上传的完整过程:

          using System;
          using System.Collections.Generic;
          using System.IO;
          using System.Linq;
          using System.Text;
          using BaiduBce;
          using BaiduBce.Auth;
          using BaiduBce.Services.Bos;
          using BaiduBce.Services.Bos.Model;
          
          namespace DotnetSample
          {
              internal class MultiUploadSample
              {
                  private static void Main(string[] args)
                  {
                      BosClient client = GenerateBosClient();
                      const string bucketName = <BucketName>;    //Bucket名称
          
                      // 初始化:创建示例Bucket
                      client.CreateBucket(bucketName);
                      string objectKey = <ObjectKey>;
          
                      // 开始Multipart Upload
                      InitiateMultipartUploadRequest initiateMultipartUploadRequest =
                          new InitiateMultipartUploadRequest() { BucketName = bucketName, Key = objectKey };
                      InitiateMultipartUploadResponse initiateMultipartUploadResponse =
                          client.InitiateMultipartUpload(initiateMultipartUploadRequest);
          
                      // 获取Bucket内的Multipart Upload
                      ListMultipartUploadsRequest listMultipartUploadsRequest =
                          new ListMultipartUploadsRequest() { BucketName = bucketName };       
                      ListMultipartUploadsResponse listMultipartUploadsResponse =
                          client.ListMultipartUploads(listMultipartUploadsRequest);
                      foreach (MultipartUploadSummary multipartUpload in listMultipartUploadsResponse.Uploads)
                      {
                          Console.WriteLine("Key: " + multipartUpload.Key + " UploadId: " + multipartUpload.UploadId);
                      }
          
                      // 分块上传,首先设置每块为 5Mb
                      long partSize = 1024 * 1024 * 5L;
                      FileInfo partFile = new FileInfo("d:\\lzb\\sample");
          
                      // 计算分块数目
                      int partCount = (int)(partFile.Length / partSize);
                      if (partFile.Length % partSize != 0)
                      {
                          partCount++;
                      }
          
                      // 新建一个List保存每个分块上传后的ETag和PartNumber
                      List<PartETag> partETags = new List<PartETag>();
                      for (int i = 0; i < partCount; i++)
                      {
                          // 获取文件流
                          Stream stream = partFile.OpenRead();
          
                          // 跳到每个分块的开头
                          long skipBytes = partSize * i;
                          stream.Seek(skipBytes, SeekOrigin.Begin);
          
                          // 计算每个分块的大小
                          long size = Math.Min(partSize, partFile.Length - skipBytes);
          
                          // 创建UploadPartRequest,上传分块
                          UploadPartRequest uploadPartRequest = new UploadPartRequest();
                          uploadPartRequest.BucketName = bucketName;
                          uploadPartRequest.Key = objectKey;
                          uploadPartRequest.UploadId = initiateMultipartUploadResponse.UploadId;
                          uploadPartRequest.InputStream = stream;
                          uploadPartRequest.PartSize = size;
                          uploadPartRequest.PartNumber = i + 1;
                          UploadPartResponse uploadPartResponse = client.UploadPart(uploadPartRequest);
          
                          // 将返回的PartETag保存到List中。
                          partETags.Add(new PartETag()
                          {
                              ETag = uploadPartResponse.ETag,
                              PartNumber = uploadPartResponse.PartNumber
                          });
          
                          // 关闭文件
                          stream.Close();
                      }
          
                      // 获取UploadId的所有Upload Part
                      ListPartsRequest listPartsRequest = new ListPartsRequest()
                      {
                          BucketName = bucketName,
                          Key = objectKey,
                          UploadId = initiateMultipartUploadResponse.UploadId,
                      };
          
                      // 获取上传的所有Part信息
                      ListPartsResponse listPartsResponse = client.ListParts(listPartsRequest);
          
                      // 遍历所有Part
                      foreach (PartSummary part in listPartsResponse.Parts)
                      {
                          Console.WriteLine("PartNumber: " + part.PartNumber + " ETag: " + part.ETag);
                      }
          
                      // 完成分块上传
                      CompleteMultipartUploadRequest completeMultipartUploadRequest =
                          new CompleteMultipartUploadRequest()
                          {
                              BucketName = bucketName,
                              Key = objectKey,
                              UploadId = initiateMultipartUploadResponse.UploadId,
                              PartETags = partETags
                          };
                      CompleteMultipartUploadResponse completeMultipartUploadResponse =
                          client.CompleteMultipartUpload(completeMultipartUploadRequest);
                      Console.WriteLine(completeMultipartUploadResponse.ETag);                  
                      Console.ReadKey();
                  }
          
                  private static BosClient GenerateBosClient()
                  {
                      const string accessKeyId = <AccessKeyID>; // 您的Access Key ID
                      const string secretAccessKey = <SecretAccessKey>; // 您的Secret Access Key
                      const string endpoint = <EndPoint>; // 指定BOS服务域名
          
                      // 初始化一个BosClient
                      BceClientConfiguration config = new BceClientConfiguration();
                      config.Credentials = new DefaultBceCredentials(accessKeyId, secretAccessKey);
                      config.Endpoint = endpoint;
          
                      return new BosClient(config);
                  }
              }
          }
          上一篇
          Bucket管理
          下一篇
          异常处理