百度智能云

All Product Document

          Object Storage

          Object Management

          Object Uploading

          The Simplest Uploading

          • Basic procedure

            1.Create an instance of the BOSClient class. 2.Call BOSClient putObject method, and upload object in the following 2 ways: Form of file and binary system 3.For the returned BOSPutObjectResponse type instance, execute the obtaining of eTag operation.

          • Sample Code

              BOSObjectContent* content = [[BOSObjectContent alloc] init];
              // In file form
              content.objectData.file = @"<file path>";
              
              // Or in binary data form
              NSData* data = [[NSData alloc] init];
              content.objectData.data = data;
              
              BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init];
              request.bucket = @"<bucketname>";
              request.key = @"<objectname>";
              request.objectContent = content;
              
              __block BOSPutObjectResponse* response = nil;
              BCETask* task = [client putObject:request];
              task.then(^(BCEOutput* output) {
                if (output.progress) {
                    NSLog(@"put object progress is %@", output.progress);
                }
              
                if (output.response) {
                    response = (BOSPutObjectResponse*)output.response;
                    NSLog(@"put object success!");
                }
              
                if (output.error) {
                    NSLog(@"put object failure");
                }
              });
              [task waitUtilFinished];

            Note: Upload object to BOS in the file form. objects no more than 5 GB can be uploaded through putObject. After the putObject request is successfully processed, BOS will return the ETag of object as a file identifier in the Header.

          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
              // Initialization
              BCECredentials* credentials = [[BCECredentials alloc] init];
              credentials.accessKey = @"<access key>";
              credentials.secretKey = @"<secret key>";
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
              configuration.credentials = credentials;
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
              BOSObjectContent* content = [[BOSObjectContent alloc] init];
              // In file form
              content.objectData.file = @"<file path>";
              
              // Or in binary data form
              NSData* data = [[NSData alloc] init];
              content.objectData.data = data;
              
              BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init];
              request.bucket = @"<bucketname>";
              request.key = @"<objectname>";
              request.objectContent = content;
              
              __block BOSPutObjectResponse* response = nil;
              BCETask* task = [client putObject:request];
              task.then(^(BCEOutput* output) {
                  if (output.progress) {
                      NSLog(@"put object progress is %@", output.progress);
                  }
              
                  if (output.response) {
                      response = (BOSPutObjectResponse*)output.response;
                      NSLog(@"put object success!");
                  }
              
                  if (output.error) {
                      NSLog(@"put object failure");
                  }
              });
              [task waitUtilFinished];
              }

          Set the Http Header of Object

          Under BOS, Http Header setting is available during object uploading.

          • Basic procedure

            1.Create instance of BOSObjectMetadata class 2.Set contentEncoding/contentType/contentDisposition and other fields of BOSObjectMetadata 3.Set BOSObjectMetadata instance to ObjectContent.metadata field of BOSPutObjectRequest.

          • Sample Code

              BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init];
              metadata.contentEncoding = @"<encoding>";
              metadata.contentDisposition = @"<content disposition>";
              content.metadata = metadata;
          • Complete example

              #import<BaiduBCEBasic/BaiduBCEBasic.h> 
              #import<BaiduBCEBOS/BaiduBCEBOS.h> 
              
              void example(void) { 
              // Initialization 
              BCECredentials* credentials = [[BCECredentials alloc] init]; 
              credentials.accessKey = @"<access key>"; 
              credentials.secretKey = @"<secret key>"; 
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; 
              configuration.credentials = credentials; 
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; 
              
              BOSObjectContent* content = [[BOSObjectContent alloc]init]; 
              // In file form 
              content.objectData.file = @"<file path>"; 
              
              // Or in binary data form 
              NSData* data = [[NSData alloc] init]; 
              content.objectData.data = data; 
              
              BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; 
              metadata.contentEncoding = @"<encoding>"; 
              metadata.contentDisposition = @"<content disposition>"; 
              content.metadata = metadata; 
              
              BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init]; 
              request.bucket = @"<bucketname>"; 
              request.key = @"<objectname>"; 
              request.ObjectContent = content; 
              
              __block BOSPutObjectResponse* response = nil; 
              BCETask* task = [client putObject:request]; 
              task.then(^(BCEOutput* output) { 
                  if (output.progress) { 
                      NSLog(@"put object progress is %@", output.progress); 
                  } 
              
                  if (output.response) { 
                      response = (BOSPutObjectResponse*)output.response; 
                      NSLog(@"put object success!"); 
                  } 
              
                  if (output.error) { 
                      NSLog(@"put object failure"); 
                  } 
              }); 
              [task waitUtilFinished]; 
              } 

          Custom Metadata

          Custom metadata is available under BOS for object description.

          • Basic procedure

            1.Create instance of BOSObjectMetadata class 2.Set custom metadata dictionary to userMetadata field of BOSObjectMetadata.

          • Sample Code

              BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; 
              metadata.contentEncoding = @"<encoding>"; 
              metadata.contentDisposition = @"<content disposition>"; 
              content.metadata = metadata; 
              
              NSDictionary* customMetadata = @{ 
                @"name" : @"my-data" 
              }; 
              content.metadata.userMetadata = customMetadata; 

            Note: As for the above code, users have customized a metadata of which the name is "name" and the value is "my-data". When users download this object, they can get metadata together. One object possesses similar parameters, but the total size of User Meta bellows 2KB.

          • Complete example

              #import<BaiduBCEBasic/BaiduBCEBasic.h> 
              #import<BaiduBCEBOS/BaiduBCEBOS.h> 
              
              void example(void) { 
              // Initialization 
              BCECredentials* credentials = [[BCECredentials alloc] init]; 
              credentials.accessKey = @"<access key>"; 
              credentials.secretKey = @"<secret key>"; 
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init]; 
              configuration.credentials = credentials; 
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration]; 
              
              BOSObjectContent* content = [[BOSObjectContent alloc]init]; 
              // In file form 
              content.objectData.file = @"<file path>"; 
              
              // Or in binary data form 
              NSData* data = [[NSData alloc] init]; 
              content.objectData.data = data; 
              
              BOSObjectMetadata* metadata = [[BOSObjectMetadata alloc] init]; 
              metadata.contentEncoding = @"<encoding>"; 
              metadata.contentDisposition = @"<content disposition>"; 
              content.metadata = metadata; 
              
              NSDictionary* customMetadata = @{ 
                  @"name" : @"my-data" 
              }; 
              content.metadata.userMetadata = customMetadata; 
              
              BOSPutObjectRequest* request = [[BOSPutObjectRequest alloc] init]; 
              request.bucket = @"<bucketname>"; 
              request.key = @"<objectname>"; 
              request.ObjectContent = content; 
              
              __block BOSPutObjectResponse* response = nil; 
              BCETask* task = [client putObject:request]; 
              task.then(^(BCEOutput* output) { 
                  if (output.progress) { 
                      NSLog(@"put object progress is %@", output.progress); 
                  } 
              
                  if (output.response) { 
                      response = (BOSPutObjectResponse*)output.response; 
                      NSLog(@"put object success!"); 
                  } 
              
                  if (output.error) { 
                      NSLog(@"put object failure"); 
                  } 
              }); 
              [task waitUtilFinished]; 
              } 

          View the Object in Bucket

          View the object list in bucket.

          • Basic procedure

            1.Create an instance of the BOSClient class. 2.Execute BOSClient listobjects method to return instance of BOSListobjectsResponse class 3.Contents field of BOSListobjectsResponse can be enumerated to obtain key/lastModified/eTag/size/owner.

          • Sample Code

              BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
              listObjRequest.bucket = @"<bucketname>";
              
              __block BOSListObjectsResponse* listObjResponse = nil;
              BCETask* task = [client listObjects:listObjRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    listObjResponse = (BOSListObjectsResponse*)output.response;
              
                    for (BOSObjectInfo* object in listObjResponse.contents) {
                        NSLog(@"the object key is %@", object.key);
                        NSLog(@"the object lastModified is %@", object.lastModified);
                        NSLog(@"the object eTag is %@", object.eTag);
                        NSLog(@"the object size is %llu", object.size);
                        NSLog(@"the object owner id is %@", object.owner.ownerID);
                    }
                }
              
                if (output.error) {
                    NSLog(@"list objects failure");
                }
              });
              [task waitUtilFinished];

            Note: Listobjects method returns BOSListobjectsResponse object which contains the return result of the current listobject request. Users can obtain descriptive information of all objects via contents attribute in BOSListobjectsResponse.

            • By default, if the number of object in bucket is more than 1,000, only 1,000 objects are returned, and the value of isTruncated in returned result is YES, and nextMarker is returned as the starting point of the next reading.
            • Use the Marker parameter to access more objects in batches. Refer to [query expansion](#query expansion).
          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
              // Initialization
              BCECredentials* credentials = [[BCECredentials alloc] init];
              credentials.accessKey = @"<access key>";
              credentials.secretKey = @"<secret key>";
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
              configuration.credentials = credentials;
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
              BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
              listObjRequest.bucket = @"<bucketname>";
              
              __block BOSListObjectsResponse* listObjResponse = nil;
              BCETask* task = [client listObjects:listObjRequest];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      listObjResponse = (BOSListObjectsResponse*)output.response;
              
                      for (BOSObjectInfo* object in listObjResponse.contents) {
                          NSLog(@"the object key is %@", object.key);
                          NSLog(@"the object lastModified is %@", object.lastModified);
                          NSLog(@"the object eTag is %@", object.eTag);
                          NSLog(@"the object size is %llu", object.size);
                          NSLog(@"the object owner id is %@", object.owner.ownerID);
                      }
                  }
              
                  if (output.error) {
                      NSLog(@"list objects failure");
                  }
              });
              [task waitUtilFinished];
              }

          Query Expansion

          You can set more extension inquiry operations by setting BOSListobjectsResquest parameters. Available extension parameters of BOSListobjectsResquest are as follows:

          Parameter name Description Default value
          maxKeys Set the maximum number of objects returned this time as 1000. 1000
          prefix Sets the prefix of ObjectKey, which covers and starts with the value of Prefix. Used in [Inquire Simulated Folder](#Inquire Simulated Folder) in cooperation with delimiter generally -
          delimiter A delimiter, used to make ObjectKey hierarchies. Used in [Inquire Simulated Folder](#Inquire Simulated Folder) in cooperation with prefix generally The ObjectKey from prefix to first appearing of delimiter character is referred to as: commonPrefixes -
          marker A character string, used to set the starting position of the returned result. After setting marker value, the object returned is returned in alphabetical order after marker value. -
          • Basic procedure

            1.Create instance of BOSListobjectsResquest type 2.Set delimiter/marker/prefix/maxKeys and other fields of BOSListobjectsResquest for more extension inquiry operations. 3.Create the instance of BOSClient class, and execute listobjects.

          • Sample Code

              BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
              listObjRequest.bucket = @"<bucketname>";
              listObjRequest.marker = @"<marker>";
              
              __block BOSListObjectsResponse* listObjResponse = nil;
              BCETask* task = [client listObjects:listObjRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    listObjResponse = (BOSListObjectsResponse*)output.response;
              
                    for (BOSObjectInfo* object in listObjResponse.contents) {
                        NSLog(@"the object key is %@", object.key);
                        NSLog(@"the object lastModified is %@", object.lastModified);
                        NSLog(@"the object eTag is %@", object.eTag);
                        NSLog(@"the object size is %llu", object.size);
                        NSLog(@"the object owner id is %@", object.owner.ownerID);
                    }
                }
              
                if (output.error) {
                    NSLog(@"list objects failure");
                }
              });
              [task waitUtilFinished];
          • Complete example

            Example I:

            #import <BaiduBCEBasic/BaiduBCEBasic.h>
            #import <BaiduBCEBOS/BaiduBCEBOS.h>
            
            void example(void) {
            // Initialization 
            BCECredentials* credentials = [[BCECredentials alloc] init];
            credentials.accessKey = @"<access key>";
            credentials.secretKey = @"<secret key>";
            BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
            configuration.credentials = credentials;
            
            BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
            
            BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
            listObjRequest.bucket = @"<bucketname>";
            listObjRequest.marker = @"<marker>";
            
            __block BOSListObjectsResponse* listObjResponse = nil;
            BCETask* task = [client listObjects:listObjRequest];
            task.then(^(BCEOutput* output) {
                if (output.response) {
                    listObjResponse = (BOSListObjectsResponse*)output.response;
            
                    for (BOSObjectInfo* object in listObjResponse.contents) {
                        NSLog(@"the object key is %@", object.key);
                        NSLog(@"the object lastModified is %@", object.lastModified);
                        NSLog(@"the object eTag is %@", object.eTag);
                        NSLog(@"the object size is %llu", object.size);
                        NSLog(@"the object owner id is %@", object.owner.ownerID);
                    }
                }
            
                if (output.error) {
                    NSLog(@"list objects failure");
                }
            });
            [task waitUtilFinished];
            }

          ​ Example II: Use the complete example of nextMarker.

          #import <BaiduBCEBasic/BaiduBCEBasic.h>
          #import <BaiduBCEBOS/BaiduBCEBOS.h>
          
          void example(void) {
          // Initialization 
          BCECredentials* credentials = [[BCECredentials alloc] init];
          credentials.accessKey = @"<access key>";
          credentials.secretKey = @"<secret key>";
          BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
          configuration.credentials = credentials;
          
          BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
          
          BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
          listObjRequest.bucket = @"<bucketname>";
          listObjRequest.marker = @"<marker>";
          
          __block BOSListObjectsResponse* listObjResponse = nil;
          BCETask* task = [client listObjects:listObjRequest];
          task.then(^(BCEOutput* output) {
              if (output.response) {
                  listObjResponse = (BOSListObjectsResponse*)output.response;
              }
          
              if (output.error) {
                  NSLog(@"list objects failure");
              }
          });
          [task waitUtilFinished];
          
          if (listObjResponse != nil) {
              listObjRequest.marker = listObjResponse.nextMarker;
              task = [client listObjects:listObjRequest];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      listObjResponse = (BOSListObjectsResponse*)output.response;
          
                      for (BOSObjectInfo* object in listObjResponse.contents) {
                          NSLog(@"the object key is %@", object.key);
                          NSLog(@"the object lastModified is %@", object.lastModified);
                          NSLog(@"the object eTag is %@", object.eTag);
                          NSLog(@"the object size is %llu", object.size);
                          NSLog(@"the object owner id is %@", object.owner.ownerID);
                      }
                  }
              });
          }
          }

          Search for Simulation Folders

          BOS itself is a storage system of (<Key>,<Value>), so there is no concept of folder in principle, but you can simulate folder function through the cooperation of delimiter and prefix parameters.

          Suppose bucket have 5 files: bos.jpg, fun/, fun/test.jpg, fun/movie/001.avi, fun/movie/007.avi ("/" can be used as a delimiter to simulate folders.)

          Lists All Files in Simulation Folders Recursively

          All folders under a simulated folder can be obtained by setting prefix parameter:

          BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
          listObjRequest.bucket = @"<bucketname>";
           listObjRequest.prefix = @"fun/";
          
          __block BOSListObjectsResponse* listObjResponse = nil;
          BCETask* task = [client listObjects:listObjRequest];
          task.then(^(BCEOutput* output) {
              if (output.response) {
                  listObjResponse = (BOSListObjectsResponse*)output.response;
          
                  for (BOSObjectInfo* object in listObjResponse.contents) {
                      NSLog(@"%@", object.key);
                  }
              }
          });
          [task waitUtilFinished];

          Output:

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

          Check the Files and Subfolders in Simulation Folders

          When prefix is combined with delimiter, the files and subdirectories under simulated folder can be listed:

          BOSListObjectsRequest* listObjRequest = [[BOSListObjectsRequest alloc] init];
          listObjRequest.bucket = @"<bucketname>";
          
          // Designate "/" as the delimiter for of simulation folders
          listObjRequest.delimiter = @"/";
          
          // List all files and subfolders in fun folders
          listObjRequest.prefix = @"fun/";
          
          __block BOSListObjectsResponse* listObjResponse = nil;
          BCETask* task = [client listObjects:listObjRequest];
          task.then(^(BCEOutput* output) {
              if (output.response) {
                  listObjResponse = (BOSListObjectsResponse*)output.response;
              }
          
              if (output.error) {
                  NSLog(@"list objects failure");
              }
          });
          [task waitUtilFinished];
          
          // Traverse all objects
          NSLog(@"Objects:");
          for (BOSObjectInfo* object in listObjResponse.contents) {
              NSLog(@"%@", object.key);
          }
          
          // Traverse all CommonPrefix
          NSLog(@"CommonPrefixs:");
          for (NSString* commonPrefix in listObjResponse.commonPrefixes) {
              NSLog(@"%@", commonPrefix);
          }

          Output:

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

          Note: In the result returned, the list of contents gives files under fun folder. The list of commonPrefixs gives all sub-folders under fun folder. It is clear that the fun/movie/001.avi file and fun/movie/007.avi file are not listed because they are the files in the movie subfolder under the fun folder.

          Access Object

          Access Object Easily

          Users can read object to memory via the following codes.

          • Basic procedure

            1.Create an instance of the BOSClient class. 2.Execute BOSClient getobject method to return BOSGetObjectResponse instance. 3.Access ObjectContent.objectData.data attribute of BOSGetObjectResponse example to obtain data.

          • Sample Code

              __block BOSGetObjectResponse* getObjResponse = nil;
              BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init];
              getObjRequest.bucket = @"<bucketname>";
              getObjRequest.key = @"<objectname>";
              BCETask* task = [client getObject:getObjRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    getObjResponse = (BOSGetObjectResponse*)output.response;
                    NSLog(@"get object success!");
                }
              
                if (output.error) {
                    NSLog(@"get object failure with %@", outpu****t.error);
                }
              
                if (output.progress) {
                    NSLog(@"the get object progress is %@", output.progress);
                }
              });
              [task waitUtilFinished];
              
              // Obtain data in memory
              NSData* data = getObjResponse.objectContent.objectData.data;

            Note:

            • BOSObjectContent contains various information of object, including bucket of object, object name, MetaData and data storage.
            • BOSObjectMetadata contains the ETag defined when the object is uploaded, the Http Header, and the custom metadata.
            • object data are obtained via objectData attribute of BOSObjectContent
          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
              // Initialization
              BCECredentials* credentials = [[BCECredentials alloc] init];
              credentials.accessKey = @"<access key>";
              credentials.secretKey = @"<secret key>";
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
              configuration.credentials = credentials;
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
              __block BOSGetObjectResponse* getObjResponse = nil;
              BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init];
              getObjRequest.bucket = @"<bucketname>";
              getObjRequest.key = @"<objectname>";
              BCETask* task = [client getObject:getObjRequest];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      getObjResponse = (BOSGetObjectResponse*)output.response;
                      NSLog(@"get object success!");
                  }
              
                  if (output.error) {
                      NSLog(@"get object failure with %@", output.error);
                  }
              
                  if (output.progress) {
                      NSLog(@"the get object progress is %@", output.progress);
                  }
              });
              [task waitUtilFinished];
              
              NSData* data = getObjResponse.objectContent.objectData.data;
              }

          Download a Part of Contents of Object

          • Basic procedure

            1.Create instance of BOSGetObjectRequest class 2.rangeStart and/or rangeEnd fields of BOSGetObjectRequestt instance 3.Execute client getobject operation.

          • Sample Code

              __block BOSGetObjectResponse* getObjResponse = nil;
              BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init];
              getObjRequest.bucket = @"<bucketname>";
              getObjRequest.key = @"<objectname>";
              
              // Obtain the first 100 bytes
              getObjRequest.rangeStart = @"0";
              getObjRequest.rangeStart = @"99";
              
              BCETask* task = [client getObject:getObjRequest];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      getObjResponse = (BOSGetObjectResponse*)output.response;
                      NSLog(@"get object success!");
                  }
              
                  if (output.error) {
                      NSLog(@"get object failure with %@", output.error);
                  }
              
                  if (output.progress) {
                      NSLog(@"the get object progress is %@", output.progress);
                  }
              });
              [task waitUtilFinished];
              
              NSData* data = getObjResponse.objectContent.objectData.data;

            Note: You can use this function for segmented download of file and breakpoint continued upload.

          Download Object to the Specified Path

          You can download object directly to the specified path through the following code.

          • Basic procedure

            1.Create instance of BOSGetObjectRequest class 2.Set the file name to be saved to file field of BOSGetObjectRequest instance. 3.Execute client getobject operation. 4.object can be downloaded to the specified path.

          • Sample Code

              __block BOSGetObjectResponse* getObjResponse = nil;
              BOSGetObjectRequest* getObjRequest = [[BOSGetObjectRequest alloc] init];
              getObjRequest.bucket = @"<bucketname>";
              getObjRequest.key = @"<objectname>";
              
              // Save file path to which the file is saved
              getObjRequest.file = @"<file>";
              
              BCETask* task = [client getObject:getObjRequest];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      getObjResponse = (BOSGetObjectResponse*)output.response;
                      NSLog(@"get object success!");
                  }
              
                  if (output.error) {
                      NSLog(@"get object failure with %@", output.error);
                  }
              
                  if (output.progress) {
                      NSLog(@"the get object progress is %@", output.progress);
                  }
              });
              [task waitUtilFinished];

          Get the StorageClass of the Object

          The storage class attribute of object is classified into STANDARD (standard storage), STANDARD_IA (infrequency storage) and COLD (cold storage)

          Sample Code

          __block BOSGetObjectMetadataResponse* getObjMetaResponse = nil;
          BCETask* task = [client getObjectMetadata:@"<bucketname>" objectKey:@"<objectname>"];
          task.then(^(BCEOutput* output) {
              if (output.response) {
                  getObjMetaResponse = (BOSGetObjectMetadataResponse*)output.response;
                  NSString storageClass = getObjMetaResponse.storageClass;
                  NSLog(@"get object storageClass success!");
              }
              if (output.error) {
                  NSLog(@"get object storageClass failure");
              }
          });
          [task waitUtilFinished];

          Get only ObjectMetadata

          Through the getObjectMetadata method, you can only get the object metadata without getting the object entity.

          • Sample Code
            __block BOSGetObjectMetadataResponse* getObjMetaResponse = nil;
            BCETask* task = [client getObjectMetadata:@"<bucketname>" objectKey:@"<objectname>"];
            task.then(^(BCEOutput* output) {
                if (output.response) {
                    getObjMetaResponse = (BOSGetObjectMetadataResponse*)output.response;
                    NSLog(@"get object metadata success!");
                }
                if (output.error) {
                    NSLog(@"get object metadata failure");
                }
            });
            [task waitUtilFinished];

          Get the URL of Object

          You can get the URL of the specified object through the following code. This feature is typically used for scenarios where you temporarily share the URL of an object with other users.

          • Basic procedure

            1.Create an instance of the BOSClient class. 2.Execute BOSClient generatePresignedUrl method 3.Return an object URL.

          • Sample Code

            __block BOSGeneratePresignedUrlResponse *generateObjetUrlRes = nil; 
             BCEOutput_ output = [client generatePresignedUrl:@"<bucketname>" objectKey:@"<objectname>" expirationInSeconds:<ExpirationInSeconds>]; 
             if (output.response) { 
                 generateObjetUrlRes = (BOSGeneratePresignedUrlResponse_)output.response; 
                 NSLog(@"get url success, the usrlstting is : %@", [generateObjetUrlRes.objectUrl absoluteString]); 
             } 
             if (output.error) { 
                 NSLog(@"get url failure, error : %@:", output.error); 
             } 

            Note: ExpirationInSeconds is the effective time length of specified URL, calculated from the current time, and it is an optional parameter; when not configured, the system default value is 1,800sec. To set a time not invalid permanently, ExpirationInSeconds parameter can be set as -1, and it cannot be set as other negative numbers.

          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
                // Initialization
                BCECredentials* credentials = [[BCECredentials alloc] init];
                credentials.accessKey = @"<access key>";
                credentials.secretKey = @"<secret key>";
                BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
                configuration.credentials = credentials;
              
                BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
                __block BOSGeneratePresignedUrlResponse *generateObjetUrlRes = nil;
              	  BCEOutput* output = [client generatePresignedUrl:@"<bucketname>" objectKey:@"<objectname>" expirationInSeconds:<ExpirationInSeconds>];
                if (output.response) {
                  generateObjetUrlRes = 	(BOSGeneratePresignedUrlResponse*)output.response;
                  NSLog(@"get url success, the usrlstting is : %@", [generateObjetUrlRes.objectUrl absoluteString]);
                }
                if (output.error) {
                  NSLog(@"get url failure, error : %@:", output.error);
                }
              }

          Delete Object

          • Basic procedure

            1.Create an instance of the BOSClient class. 2.Execute BOSClient deleteobject method 3.If an error is generated after operation fails.

          • Sample Code
             __block BOSDeleteObjectResponse* response = nil;
             BCETask* task = [client deleteObject:@"<bucketname>" objectKey:@"<objectname>"];
             task.then(^(BCEOutput* output) {
                 if (output.response) {
                     response = (BOSDeleteObjectResponse*)output.response;
                     NSLog(@"delete obj success!");
                 }
                 if (output.error) {
                     NSLog(@"delete obj failure");
                 }
             });
             [task waitUtilFinished];
          • Complete example
            #import <BaiduBCEBasic/BaiduBCEBasic.h>
            #import <BaiduBCEBOS/BaiduBCEBOS.h>
            void example(void) {
                // initialization
                BCECredentials* credentials = [[BCECredentials alloc] init];
                credentials.accessKey = @"<access key>";
                credentials.secretKey = @"<secret key>";
                BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
                configuration.credentials = credentials;
                BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
          
                __block BOSDeleteObjectResponse* response = nil;
                BCETask* task = [client deleteObject:@"<bucketname>" objectKey:@"<objectname>"];
                task.then(^(BCEOutput* output) {
                    if (output.response) {
                        response = (BOSDeleteObjectResponse*)output.response;
                        NSLog(@"delete obj success!");
                    }
                
                    if (output.error) {
                        NSLog(@"delete obj failure");
                    }
                });
                [task waitUtilFinished];
                }

          Copy Object

          Simply copy object

          • Basic procedure

            1.Create an instance of the BOSClient class. 2.Execute BOSClient copyobject method. 3.Return BOSCopyObjectResponse instance to obtain eTag and last modification time via eTag/lastModified and other attributes.

          • Sample Code

              BOSCopyObjectRequest* request = [[BOSCopyObjectRequest alloc] init];
              request.bucket = @"<bucketname>";
              request.key = @"<objectname>";
              request.source = @"<sourceBucket>/<sourceObject";
              
              __block BOSCopyObjectResponse* response = nil;
              BCETask* task = [client copyObject:request];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      response = (BOSCopyObjectResponse*)output.response;
                      NSLog(@"copy obj success!");
                  }
              
                  if (output.error) {
                      NSLog(@"copy obj failure");
                  }
              });
              [task waitUtilFinished];
          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
                // Initialization
                BCECredentials* credentials = [[BCECredentials alloc] init];
                credentials.accessKey = @"<access key>";
                credentials.secretKey = @"<secret key>";
                BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
                configuration.credentials = credentials;
              
                BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
                BOSCopyObjectRequest* request = [[BOSCopyObjectRequest alloc] init];
                request.bucket = @"<bucketname>";
                request.key = @"<objectname>";
                request.source = @"<sourceBucket>/<sourceObject";
              
                __block BOSCopyObjectResponse* response = nil;
                BCETask* task = [client copyObject:request];
                task.then(^(BCEOutput* output) {
                    if (output.response) {
                        response = (BOSCopyObjectResponse*)output.response;
                        NSLog(@"copy obj success!");
                    }
              
                    if (output.error) {
                        NSLog(@"copy obj failure");
                    }
                });
                [task waitUtilFinished];
              }

            Note: Copyobject method returns a BOSCopyObjectResponse object which contains the ETag and modification time of a new object.

          Copy Object of Specified Condition

          You can also copy object via a specified condition This feature is typically used in the following scenarios:

          • Copy an object but reset the meta.
          • Set the meta of an existing object (set the source and target as the same object)
          • Copy when the eTag of source object is the same with the specified eTag
          • Copy when the eTag of source object is different from the specified eTag
          • Copy when the eTag of source object is not modified after the specified time;
          • Copy when the eTag of source object is modified after the specified time;

          The specific contents are as follows:

          • Basic procedure

            1.Create instance of BOSCopyObjectRequest class, transmit <source>,<ifMatchEtag>, <ifNotMatchEtag>,<ifModifiedSince>,<ifUnmodifiedSince>, <metadataDirective> parameters. 2.Return instance of BOSCopyObjectResponse class, and eTag and last modification time can be obtained via eTag/lastModified attribute.

          • Sample Code

              BOSCopyObjectRequest* request = [[BOSCopyObjectRequest alloc] init];
              request.bucket = @"<bucketname>";
              request.key = @"<objectname>";
              request.source = @"<sourceBucket>/<sourceObject";
              request.metadataDirective = @"replace";
              request.ifModifiedSince = @"Wed, 01 Mar 2006 12:00:00 GMT";
              
              __block BOSCopyObjectResponse* response = nil;
              BCETask* task = [client copyObject:request];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    response = (BOSCopyObjectResponse*)output.response;
                    NSLog(@"copy obj success!");
                }
              
                if (output.error) {
                    NSLog(@"copy obj failure");
                }
              });
              [task waitUtilFinished];

            Note: BOSCopyObjectRequest allows users to modify objectMeta of destination object, whole providing setting of MatchingETagConstraints parameter.

          Multipart Upload of Object

          In addition to uploading files to BOS through putObject () method, BOS also provides another upload mode: Multipart Upload. You can use the Multipart Upload mode in the following application scenarios (but not limited to this), such as:

          • Breakpoint upload support is required.
          • The file to upload is larger than 5 GB.
          • The network conditions are poor, and the connection with BOS servers is often disconnected.
          • The file needs to be uploaded streaming.
          • The size of the uploaded file cannot be determined before uploading it.

          Complete Multipart Upload

          Suppose you have a file with the local path of /path/to/file.zip, upload it through Multipart Upload to BOS for its large size.

          • Basic procedure

            1.Initialize Multipart Upload. 2.Upload in parts. 3.Complete Multipart Upload.

          Initialize Multipart Upload

          Use the initiateMultipartUpload method to initialize a Multipart Upload event:

          • Sample Code

              BOSInitiateMultipartUploadRequest* initMPRequest = [[BOSInitiateMultipartUploadRequest alloc] init];
              initMPRequest.bucket = @"<bucketname>";
              initMPRequest.key = @"<objectname>";
              initMPRequest.contentType = @"<content type>";
              
              __block BOSInitiateMultipartUploadResponse* initMPResponse = nil;
              BCETask* task = [client initiateMultipartUpload:initMPRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    initMPResponse = (BOSInitiateMultipartUploadResponse*)output.response;
                    NSLog(@"initiate multipart upload success!");
                }
              
                if (output.error) {
                    NSLog(@"initiate multipart upload failure");
                }
              });
              [task waitUtilFinished];
              
              NSString* uploadID = initMPResponse.uploadId;

            Note: The returned result of initiateMultipartUpload contains uploadId, which is the unique identification to distinguish upload by event part, and we will use it in the subsequent operation.

          Upload in Parts

          Upload files in parts.

          • Sample Code

              // Calculate number of parts
              NSString* file = @"/path/to/file.zip";
              NSDictionary<NSString*, id>* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil];
              uint64_t fileSize = attr.fileSize;
              uint64_t partSize = 1024 * 1024 * 5L;
              uint64_t partCount = fileSize / partSize;
              if (fileSize % partSize != 0) {
                ++partCount;
              }
              
              NSMutableArray<BOSPart*>* parts = [NSMutableArray array];
              NSFileHandle* handle = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/file.zip"];
              for (uint64_t i = 0; i < partCount; ++i) {
                // seek
                uint64_t skip = partSize * i;
                [handle seekToFileOffset:skip];
                uint64_t size = (partSize < fileSize - skip) ? partSize : fileSize - skip;
              
                // data
                NSData* data = [handle readDataOfLength:size];
              
                // request
                BOSUploadPartRequest* uploadPartRequest = [[BOSUploadPartRequest alloc] init];
                uploadPartRequest.bucket = @"<bucketname>";
                uploadPartRequest.key = @"<objectname>";
                uploadPartRequest.objectData.data = data;
                uploadPartRequest.partNumber = i + 1;
                uploadPartRequest.uploadId = uploadID;
              
                __block BOSUploadPartResponse* uploadPartResponse = nil;
                task = [client uploadPart:uploadPartRequest];
                task.then(^(BCEOutput* output) {
                    if (output.response) {
                        uploadPartResponse = (BOSUploadPartResponse*)output.response;
                        BOSPart* part = [[BOSPart alloc] init];
                        part.partNumber = i + 1;
                        part.eTag = uploadPartResponse.eTag;
              				  [parts addObject:part];
                    }
                });
                [task waitUtilFinished];
              }

            Note: The core of the code above is to call uploadPart method to upload each part, but the following need to be noted:

            • The UploadPart method requires that all but the last Part be larger than or equal to 5 MB. However, the Upload Part interface does not immediately verify the size of the Upload Part. It verifies only in case of Complete Multipart Upload.
            • To ensure no error occurs to data in the network transmission process, it is recommended that you use the Content-MD5 value returned by each part BOS to verify the correctness of the uploaded part data respectively after UploadPart. When all part data is combined into one object, it no longer contains the MD5 value.
            • Part numbers range from 1 to 10,000. If this range is exceeded, BOS will return the error code of InvalidArgument.
            • Every time you upload a Part, locate the stream to the location corresponding to the beginning of the uploaded part.
            • After uploading Part each time, the returned result of BOS contains a BOSPart object, which is the combination of ETag of uploaded part and PartNumber, and will be used in the subsequent multipart upload, so it needs to be saved. Generally, these BOSPart objects are saved in List.

          Complete Multipart Upload

          • Sample Code

              BOSCompleteMultipartUploadRequest* compMultipartRequest = [[BOSCompleteMultipartUploadRequest alloc] init];
              compMultipartRequest.bucket = @"<bucketname>";
              compMultipartRequest.key = @"<objectname>";
              compMultipartRequest.uploadId = uploadID;
              compMultipartRequest.parts = parts;
              
              __block BOSCompleteMultipartUploadResponse* complResponse = nil;
              task = [client completeMultipartUpload:compMultipartRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    complResponse = (BOSCompleteMultipartUploadResponse*)output.response;
                    NSLog(@"complte multiparts success!");
                }
              
                if (output.error) {
                    NSLog(@"complte multiparts failure %@", output.error);
                }
              });
              [task waitUtilFinished];

            Note: The parts in the code above are the list of parts saved in Step 2 and BOS checks the validity of each data Part after receiving the Part list submitted by users. When all data Parts are verified, BOS will combine these data parts into a complete object.

          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
              // Initialization
              BCECredentials* credentials = [[BCECredentials alloc] init];
              credentials.accessKey = @"<access key>";
              credentials.secretKey = @"<secret key>";
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
              configuration.credentials = credentials;
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
              // Initialize multipart upload
              BOSInitiateMultipartUploadRequest* initMPRequest = [[BOSInitiateMultipartUploadRequest alloc] init];
              initMPRequest.bucket = @"<bucketname>";
              initMPRequest.key = @"<objectname>";
              initMPRequest.contentType = @"<content type>";
              
               __block BOSInitiateMultipartUploadResponse* initMPResponse = nil;
               BCETask* task = [client initiateMultipartUpload:initMPRequest];
               task.then(^(BCEOutput* output) {
                   if (output.response) {
                       initMPResponse = (BOSInitiateMultipartUploadResponse*)output.response;
                       NSLog(@"initiate multipart upload success!");
                   }
              
                   if (output.error) {
                       NSLog(@"initiate multipart upload failure");
                   }
               });
               [task waitUtilFinished];
              
               NSString* uploadID = initMPResponse.uploadId;
              
               // Calculate number of parts
               NSString* file = @"/path/to/file.zip";
               NSDictionary<NSString*, id>* attr = [[NSFileManager defaultManager] attributesOfItemAtPath:file error:nil];
               uint64_t fileSize = attr.fileSize;
               uint64_t partSize = 1024 * 1024 * 5L;
               uint64_t partCount = fileSize / partSize;
               if (fileSize % partSize != 0) {
                   ++partCount;
               }
              
               NSMutableArray<BOSPart*>* parts = [NSMutableArray array];
              
               NSFileHandle* handle = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/file.zip"];
               for (uint64_t i = 0; i < partCount; ++i) {
                   // seek
                   uint64_t skip = partSize * i;
                   [handle seekToFileOffset:skip];
                   uint64_t size = (partSize < fileSize - skip) ? partSize : fileSize - skip;
              
                   // data
                   NSData* data = [handle readDataOfLength:size];
              
                   // request
                   BOSUploadPartRequest* uploadPartRequest = [[BOSUploadPartRequest alloc] init];
                   uploadPartRequest.bucket = @"<bucketname>";
                   uploadPartRequest.key = @"<objectname>";
                   uploadPartRequest.objectData.data = data;
                   uploadPartRequest.partNumber = i + 1;
                   uploadPartRequest.uploadId = uploadID;
              
                   __block BOSUploadPartResponse* uploadPartResponse = nil;
                   task = [client uploadPart:uploadPartRequest];
                   task.then(^(BCEOutput* output) {
                       if (output.response) {
                           uploadPartResponse = (BOSUploadPartResponse*)output.response;
                           BOSPart* part = [[BOSPart alloc] init];
                           part.partNumber = i + 1;
                           part.eTag = uploadPartResponse.eTag;
              					 [parts addObject:part];
                       }
                   });
                   [task waitUtilFinished];
               }
              
               BOSCompleteMultipartUploadRequest* compMultipartRequest = [[BOSCompleteMultipartUploadRequest alloc] init];
               compMultipartRequest.bucket = @"<bucketname>";
               compMultipartRequest.key = @"<objectname>";
               compMultipartRequest.uploadId = uploadID;
               compMultipartRequest.parts = parts;
              
               __block BOSCompleteMultipartUploadResponse* complResponse = nil;
               task = [client completeMultipartUpload:compMultipartRequest];
               task.then(^(BCEOutput* output) {
                   if (output.response) {
                       complResponse = (BOSCompleteMultipartUploadResponse*)output.response;
                       NSLog(@"complte multiparts success!");
                   }
              
                   if (output.error) {
                       NSLog(@"complte multiparts failure %@", output.error);
                   }
               });
               [task waitUtilFinished];
              }

          Cancel Multipart Upload

          You can use the abortMultipartUpload method to cancel Multipart Upload.

          • Sample Code

              BOSAbortMultipartUploadRequest* abortRequest = [[BOSAbortMultipartUploadRequest alloc] init];
              abortRequest.bucket = @"bucket";
              abortRequest.key = @"<objectname>";
              abortRequest.uploadId = uploadID;
              
              __block BOSAbortMultipartUploadResponse* abortResponse = nil;
              task = [client abortMultipartUpload:abortRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    abortResponse = (BOSAbortMultipartUploadResponse*)output.response;
                    NSLog(@"abort multiparts success!");
                }
              
                if (output.error) {
                    NSLog(@"abort multiparts failure %@", output.error);
                }
              });
              [task waitUtilFinished];

          Get Unfinished Multipart Upload

          You can use the listMultipartUploads method to get unfinished Multipart Upload events in the bucket.

          • Basic procedure

            1.Create the instance of BOSListMultipartUploadsRequest class, and introduce <BucketName> parameter. 2.Create instance of BOSClient, and execute BOSClient listMultipartUploads method. 3.ListMultipartUploads returns all uncompleted multipart upload information.

          • Sample Code

              BOSListMultipartUploadsRequest* listMultipartRequest = [[BOSListMultipartUploadsRequest alloc] init];
              listMultipartRequest.bucket = @"<bucketname>";
              
              __block BOSListMultipartUploadsResponse* listMultipartResponse = nil;
              task = [client listMultipartUploads:listMultipartRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    listMultipartResponse = (BOSListMultipartUploadsResponse*)output.response;
                    NSLog(@"list multipart success");
                }
              
                if (output.error) {
                    NSLog(@"list multipart failure %@", output.error);
                }
              });
              [task waitUtilFinished];

            Note:

            • By default, only 1,000 objects are returned and the IsTruncated value is True if the number of Multipart Upload events in bucket is over 1,000. Besides, NextKeyMarker is returned as the starting point for the next reading.
            • For more Multipart Upload events, you can use the KeyMarker parameter to read them by several times.
          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
                // Initialization
                BCECredentials* credentials = [[BCECredentials alloc] init];
                credentials.accessKey = @"<access key>";
                credentials.secretKey = @"<secret key>";
                BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
                configuration.credentials = credentials;
              
                BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
                BOSListMultipartUploadsRequest* listMultipartRequest = [[BOSListMultipartUploadsRequest alloc] init];
                listMultipartRequest.bucket = @"<bucketname>";
              
                __block BOSListMultipartUploadsResponse* listMultipartResponse = nil;
                BCETask* task = [client listMultipartUploads:listMultipartRequest];
                task.then(^(BCEOutput* output) {
                    if (output.response) {
                        listMultipartResponse = (BOSListMultipartUploadsResponse*)output.response;
                        NSLog(@"list multipart success");
                    }
              
                    if (output.error) {
                        NSLog(@"list multipart failure %@", output.error);
                    }
                });
                [task waitUtilFinished];
              
                for (BOSMultipartUpload* upload in listMultipartResponse.uploads) {
                    NSLog(@"upload id : %@", upload.uploadId);
                }
              }

          Get All Uploaded Part Information

          You can use the listParts method to get all uploaded parts in an uploaded event.

          • Basic procedure

            1.Create instance of BOSListPartsRequest class, and introduce <BucketName>,<ObjectKey>, <UploadId> parameters. 2.Create the instance of BOSClient class, and execute BOSClient listParts method. 3.listParts returns information about all uploaded parts.

          • Sample Code

              BOSListPartsRequest* listPartsRequest = [[BOSListPartsRequest alloc] init];
              listPartsRequest.bucket = @"<bucketname>";
              listPartsRequest.key = @"<objectname>";
              listPartsRequest.uploadId = @"<upload id>";;
              
              __block BOSListPartsResponse* listPartsResponse = nil;
              BCETask* task = [client listParts:listPartsRequest];
              task.then(^(BCEOutput* output) {
                if (output.response) {
                    listPartsResponse = (BOSListPartsResponse*)output.response;
                    NSLog(@"list parts success!");
                }
              
                if (output.error) {
                    NSLog(@"list part failure %@", output.error);
                }
              });
              [task waitUtilFinished];
              
              for (BOSPart* part in listPartsResponse.parts) {
                  NSLog(@"part etag %@", part.eTag);
              }

            Note:

            • By default, only 1,000 objects are returned and the IsTruncated value is True if the number of Multipart Upload events in bucket is over 1,000. Besides, NextPartNumberMarker is returned as the starting point for the next reading.
            • For more uploaded part information, you can use the PartNumberMarker parameter to read it by several times.
          • Complete example

              #import <BaiduBCEBasic/BaiduBCEBasic.h>
              #import <BaiduBCEBOS/BaiduBCEBOS.h>
              
              void example(void) {
              // Initialization
              BCECredentials* credentials = [[BCECredentials alloc] init];
              credentials.accessKey = @"<access key>";
              credentials.secretKey = @"<secret key>";
              BOSClientConfiguration* configuration = [[BOSClientConfiguration alloc] init];
              configuration.credentials = credentials;
              
              BOSClient* client = [[BOSClient alloc] initWithConfiguration:configuration];
              
              BOSListPartsRequest* listPartsRequest = [[BOSListPartsRequest alloc] init];
              listPartsRequest.bucket = @"<bucketname>";
              listPartsRequest.key = @"<objectname>";
              listPartsRequest.uploadId = @"<upload id>";;
              
              __block BOSListPartsResponse* listPartsResponse = nil;
              BCETask* task = [client listParts:listPartsRequest];
              task.then(^(BCEOutput* output) {
                  if (output.response) {
                      listPartsResponse = (BOSListPartsResponse*)output.response;
                      NSLog(@"list parts success!");
                 }
              
                 if (output.error) {
                      NSLog(@"list part failure %@", output.error);
                 }
              });
              [task waitUtilFinished];
              
              for (BOSPart* part in listPartsResponse.parts) {
                  NSLog(@"part etag %@", part.eTag);
              }
              }
          Previous
          Bucket Management
          Next
          Log