所有文档

          对象存储 BOS

          Object管理

          上传Object

          最简单的上传

          • 基本流程

            1. 创建BOSClient 类的实例。
            2. 调用BOSClient.putObject()方法,可以通过如下四种方式上传Object:文件、数据流、二进制串和字符串的形式。
            3. 对返回的PutObjectResponse类型实例,执行getETag()获得上传成功的ETag。
          • 示例代码

            // 获取指定文件
            File file = new File(<FilePath>);     //指定文件路径
            
            // 以文件形式上传Object
            PutObjectResponse putObjectFromFileResponse = 
                client.putObject(<BucketName>, <ObjectKey>, file);
            
            // 获取数据流
            InputStream inputStream = new FileInputStream(<FilePath>);
            
            // 以数据流形式上传Object
            PutObjectResponse putObjectResponseFromInputStream = 
                client.putObject(<BucketName>, <ObjectKey>, inputStream);
            
            // 以二进制串上传Object
            PutObjectResponse putObjectResponseFromByte = 
                client.putObject(<BucketName>, <ObjectKey>, <byte>);
            
            // 以字符串上传Object
            PutObjectResponse putObjectResponseFromString = 
                client.putObject(<BucketName>, <ObjectKey>, <string>);
            
            // 打印ETag
            System.out.println(putObjectFromFileResponse.getETag());

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

          • 完整示例

            import java.io.File;
            import java.io.FileInputStream;
            import java.io.FileNotFoundException;
            import java.io.InputStream;
            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.development.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.PutObjectResponse;public class ExampleActivity extends Activity {
            
              private String bucketName = <BucketName>;
              private String objectKey = <ObjectKey>;
              byte[] b = null;
              String str = <PutString>;
            
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 获取指定文件
                            File file = new File("/path/to/file.zip");
            
                            // 以文件形式上传Object
                            PutObjectResponse putObjectFromFileResponse = client.putObject(<BucketName>, <ObjectKey>, file);
            
                            // 获取数据流
                            InputStream inputStream = new FileInputStream("/path/to/test.zip");
            
                            // 以数据流形式上传Object
                            PutObjectResponse putObjectResponseFromInputStream = client.putObject(<BucketName>, <ObjectKey>, inputStream);
            
                            // 以二进制串上传Object
                            PutObjectResponse putObjectResponseFromByte = client.putObject(<BucketName>, <ObjectKey>, b);
            
                            // 以字符串上传Object
                            PutObjectResponse putObjectResponseFromString = client.putObject(<BucketName>, <ObjectKey>, str);
            
                            // 打印ETag
                            System.out.println(putObjectFromFileResponse.getETag());
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (FileNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } 
                    }
                }).start();
            }}

          设定Object的Copy属性

          CopyObject接口用于将一个已经存在的Object拷贝到另外一个Object,拷贝过程中会对源Object的Etag或修改状态进行判断,根据判断结果决定是否执行拷贝。详细的参数解释如下:

          名称 类型 描述 是否必需
          x-bce-copy-source-if-match String 如果源Object的ETag值和用户提供的ETag相等,则执行拷贝操作,否则拷贝失败。
          x-bce-copy-source-if-none-match String 如果源Object的ETag和用户提供的ETag不相等,则执行拷贝操作,否则拷贝失败。
          x-bce-copy-source-if-unmodified-since String 如果源object在x-bce-copy-source-if-unmodified-since之后没被修改,则执行拷贝操作,否则拷贝失败。
          x-bce-copy-source-if-modified-since String 如果源object在x-bce-copy-source-if-modified-since之后被修改了,则执行拷贝操作,否则拷贝失败。
          • 示例代码

            // 初始化BosClient
            BosClient client = ...;
            
            // 创建CopyObjectRequest对象
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(srcBucketName, srcKey, destBucketName, destKey);
            
            // 设置新的Metadata
            Map<String, String> userMetadata = new HashMap<String, String>();
            userMetadata.put("<user-meta-key>","<user-meta-value>");
            ObjectMetadata meta = new ObjectMetadata();
            meta.setUserMetadata(userMetadata);
            copyObjectRequest.setNewObjectMetadata(meta);
            
            //copy-source-if-match
            copyObjectRequest.withETag("111111111183bf192b57a4afc76fa632");
            //copy-source-if-none-match
            copyObjectRequest.withNoMatchingETagConstraint("111111111183bf192b57a4afc76fa632");
            
            Date modifiedSinceConstraint = new Date();    
            SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);  
            df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));        
            String date = df.format(modifiedSinceConstraint);
            
            //copy-source-if-modified-since
            copyObjectRequest.withModifiedSinceConstraint(date);
            
            //copy-source-if-unmodified-since
            copyObjectRequest.withUnmodifiedSinceConstraint(date);
            
            // 复制Object
            CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);

          设定Object的Http Header

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

          • 基本流程

            1. 创建ObjectMetadata类的实例。
            2. 执行setContentLength()/setContentType()等方法对Http Header进行设定。
            3. 将设定后的meta作为参数加入client.putObject()中。
          • 示例代码

            // 创建ObjectMetadata类的实例
            ObjectMetadata meta = new ObjectMetadata();
            
            // 设置ContentLength大小
            meta.setContentLength(<Length>);
            
            // 设置ContentType
            meta.setContentType("application/json");
            
            client.putObject(<BucketName>, <ObjectKey>, content, meta);

            说明:header可设置的属性有:"Cache-Control"、"Content-Encoding"、"Content-Disposition"、"Expires"

          • 完整示例

            import java.io.FileInputStream;
            import java.io.FileNotFoundException;
            import java.io.InputStream;
            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.ObjectMetadata;
            import com.baidubce.services.bos.model.PutObjectResponse;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 获取数据流
                            InputStream inputStream = new FileInputStream("/path/to/test.zip");
            
                            // 创建ObjectMetadata类的实例
                            ObjectMetadata meta = new ObjectMetadata();
            
                            // 设置ContentLength大小
                            meta.setContentLength(1000);
            
                            // 设置ContentType
                            meta.setContentType("application/json");
            
                            PutObjectResponse putObjectResponseFromInputStream = client.putObject(bucketName, objectKey, inputStream, meta);
            
                             // 打印ETag
                            System.out.println(putObjectResponseFromInputStream.getETag());
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (FileNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } 
                    }
                }).start();
            }}

          用户自定义元数据

          BOS支持用户自定义元数据来对Object进行描述。

          • 基本流程

            1. 创建ObjectMetadata类的实例。
            2. 执行addUserMetadata()方法对Http Header进行自定义元数据。
            3. 将设定后的meta作为参数加入client.putObject()中。
          • 示例代码

            // 设置自定义元数据name的值为my-data
            meta.addUserMetadata("name", "my-data");	  
            
            // 上传Object
            client.putObject(<BucketName>, <ObjectKey>, <Content>, meta);

            说明:在上面代码中,用户自定义了一个名字为”name”,值为”my-data”的元数据。当用户下载此Object的时候,此元数据也可以一并得到。一个Object可以有多个类似的参数,但所有的User Meta总大小不能超过2KB。

          • 完整示例

            import java.io.FileInputStream;
            import java.io.FileNotFoundException;
            import java.io.InputStream;
            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.ObjectMetadata;
            import com.baidubce.services.bos.model.PutObjectResponse;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 获取数据流
                            InputStream inputStream = new FileInputStream("/path/to/test.zip");
            
                            // 创建ObjectMetadata类的实例
                            ObjectMetadata meta = new ObjectMetadata();
            
                            // 自定义元数据
                            meta.addUserMetadata("name", "my-data");	    
            
                            PutObjectResponse putObjectResponseFromInputStream = client.putObject(<BucketName>, <ObjectKey>, inputStream, meta);
            
                             // 打印ETag
                            System.out.println(putObjectResponseFromInputStream.getETag());
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (FileNotFoundException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } 
                    }
                }).start();
            }}

          Append方式上传Object

          BOS支持AppendObject,即以追加写的方式上传文件,适用场景如日志追加及直播等实时视频文件上传。通过AppendObject操作创建的Object类型为Appendable Object,可以对该Object追加数据;而通过PutObject上传的Object是Normal Object,不可进行数据追加写。AppendObject大小限制为0~5G。

          • 示例代码

            public void AppendObject(BosClient client, String bucketName, String objectKey, byte[] byte1, String string1) {
                  // 获取指定文件
                  File file = new File("/path/to/file.zip");
                  // 获取数据流
                  InputStream inputStream = new FileInputStream("/path/to/test.zip");
            
                  // 以文件形式上传Object
                  AppendObjectResponse appendObjectFromFileResponse = client.appendObject(bucketName, objectKey, file);
                  // 以数据流形式上传Object
                  AppendObjectResponse appendObjectResponseFromInputStream = client.appendObject(bucketName, objectKey, inputStream);
                  // 以二进制串上传Object
                  AppendObjectResponse appendObjectResponseFromByte = client.appendObject(bucketName, objectKey, byte1);
                  // 以字符串上传Object
                  AppendObjectResponse appendObjectResponseFromString = client.appendObject(bucketName, objectKey, string1);
            
                  // 向AppendFile追加内容
                  Long nextOffset = appendObjectFromFileResponse.getNextAppendOffset();
                  AppendObjectRequest request =new AppendObjectRequest(bucketName, objectKey,
                  RestartableInputStream.wrap(string1.getBytes()));
                  request.withOffset(nextOffset);
                  AppendObjectResponse appendResponse = client.appendObject(request);      
            }

          获取上传进度

          Android SDK支持在上传过程中实时提供上传进度信息。目前支持PutObject, AppendObject, UploadPart以及PutSuperObjectFromFile四个接口。进度上传接口的使用必须构造对应的Request (PutObjectRequest, AppendObjectRequest, UploadPartRequest以及PutSuperObjectRequest)。

          SDK提供的上传进度回调接口如下,您可以在其中定义上传过程中您所需要的操作,如更新界面等等。

          public interface BceProgressCallback<T extends AbstractBceRequest> {
                // request为上传的请求
                // currentSize为当前上传的大小(单位:byte)
                // totalSize为本次请求需要上传的总大小(单位:byte)
                void onProgress(T request, long currentSize, long totalSize);
          • PutObject示例代码:

            PutObjectRequest request = new PutObjectRequest(this.bucketName, "test", file);
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType("text/plain");
            request.setObjectMetadata(objectMetadata);
            request.setProgressCallback(new BosProgressCallback<PutObjectRequest>() {
                @Override
                public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {
                    Log.e(currentSize + "", totalSize + "");
                }
            });
            String eTag = this.client.putObject(request).getETag();
          • AppendObject示例代码:

            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType("text/plain");
            AppendObjectRequest request = new AppendObjectRequest(this.bucketName, "test", file);
            request.setObjectMetadata(objectMetadata);
            AppendObjectResponse response = this.client.appendObject(request);
            Long nextOffset = response.getNextAppendOffset();
            request.withOffset(nextOffset);
            request.setProgressCallback(new BosProgressCallback<AppendObjectRequest>() {
                @Override
                public void onProgress(AppendObjectRequest request, long currentSize, long totalSize) {
                    Log.e(currentSize + "", totalSize + "");
                }
            });
            response = this.client.appendObject(request);
          • UploadPart示例代码:

            UploadPartRequest request = new UploadPartRequest().withBucketName(this.bucketName)
                    .withKey("test").withUploadId(uploadId).withPartNumber(1).withPartSize(8000)
                    .withInputStream(fis);
            request.setProgressCallback(new BosProgressCallback<UploadPartRequest>() {
                @Override
                public void onProgress(UploadPartRequest request, long currentSize, long totalSize) {
                    Log.e(currentSize + "", totalSize + "");
                }
            });
            UploadPartResponse response = this.client.uploadPart(request);
          • PutSuperObjectFromFile示例代码:

            PutSuperObjectRequest request = new PutSuperObjectRequest().withBucketName(this.bucketName)
                    .withKey("test").withPartSize(1024*1024*2L).withFile(file);
            request.setProgressCallback(new BosProgressCallback<PutSuperObjectRequest>() {
                @Override
                public void onProgress(PutSuperObjectRequest request, long currentSize, long totalSize) {
                    Log.e(currentSize + "", totalSize + "");
                }
            });
            PutSuperObjectResponse response = this.client.putSuperObjectFromFile(request);

            目前,SDK默认上传进度的回调粒度为2048个字节。您可以通过如下方法设置一个更适合您App应用的回调粒度:

            BosClientConfiguration config=new BosClientConfiguration(); config.setUploadSegmentPart(1024);

          注意: 该值必须在1-8192之间,如不在该范围内,Android SDK会强制设置为2048.

          取消接口

          Android SDK支持在请求过程中取消本次请求,其中上传请求中剩余的数据将不再会上传至BOS,下载请求中取消操作会关闭连接,执行中的操作会抛出Request is canceled!异常

          所有的BOS操作都可以使用取消接口,但是已经完成的请求无法被取消,已经完成的操作也不会抛出异常

          // 以上传接口取消为例
          final PutObjectRequest req = new PutObjectRequest(<BucketName>, <ObjectName>,
                   new FileInputStream(<FilePath>));
          Runnable cancelTask = new Runnable() {
              @Override
              public void run() {
                  try {
                      Thread.sleep(100);
                  } catch (InterruptedException e) {
                      e.printStackTrace()
                  }
                  // 取消本次上传请求
                  req.cancel();
              }
          };
          new Thread(cancelTask).start();
          client.putObject(req);

          同步回调

          Android SDK支持BOS服务端同步回调接口,通过在PutObjectRequest中,设置process参数,就可以在上传完成后,让BOS服务端主动调用回调接口来达到通知客户目的。

          PutObjectRequest request = new PutObjectRequest({bucket}, {object}, {inputStream});
          // 设置x-bce-process参数
          request.setProcess({x-bce-process});
          PutObjectResponse response = client.putObject(request);
          // 获取返回的http status code
          int statusCode = response.getHttpResponse().getStatusCode();
          // 获取返回的回调接口返回的数据
          string callbackString = response.getServerCallbackReturnBody();

          查看Bucket中的Object

          简单查询

          查看Bucket中Object列表。

          • 基本流程

            1. 创建BOSClient类的实例。
            2. 执行BOSClient.listObjects(bucketName)方法,会返回ListObjectsResponse类的实例。
            3. 对ListObjectsResponse类型可以进行getBuckets()/getOwner()/getMetadata()操作。
          • 示例代码

            // 获取指定Bucket下的所有Object信息
            ListObjectsResponse listing = client.listObjects(<BucketName>);
            
            // 遍历所有Object
            for (BosObjectSummary objectSummary : listing.getContents()) {
                System.out.println("ObjectKey: " + objectSummary.getKey());
            }

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

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

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.BosObjectSummary;
            import com.baidubce.services.bos.model.ListObjectsResponse;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyId>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 获取指定Bucket下的所有Object信息
                            ListObjectsResponse listing = client.listObjects(<BucketName>);
            
                            // 遍历所有Object
                            for (BosObjectSummary objectSummary : listing.getContents()) {
                                System.out.println("ObjectKey: " + objectSummary.getKey());
                            }               	                    
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        }
                    }
                }).start();
            }}

          扩展查询

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

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

            1. 创建ListObjectsRequest类的实例。
            2. 在ListObjectsRequest中执行setDelimiter/setMarker()/setPrefix()等方法,实现更多的扩展查询操作。
            3. 创建BOSClient类的实例,执行listObjects(listObjectsRequest)。
          • 示例代码

            // 构造ListObjectsRequest请求
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(<BucketName>);  
            
            // 设置扩展查询参数
            listObjectsRequest.setDelimiter(<Delimiter>);
            listObjectsRequest.setMarker(<Marker>);
            ...   
            ListObjectsResponse listing = client.listObjects(listObjectsRequest);

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

          • 完整示例

            示例一:

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.BosObjectSummary;
            import com.baidubce.services.bos.model.ListObjectsRequest;
            import com.baidubce.services.bos.model.ListObjectsResponse;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 构造ListObjectsRequest请求
                            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(<BucketName>); 
            
                            // 设置参数
                            listObjectsRequest.setDelimiter("/");
                            listObjectsRequest.setMarker("123");
                            listObjectsRequest.setMaxKeys(100);
                            listObjectsRequest.setPrefix("fun");
            
                            // 获取指定Bucket下符合上述条件的所有Object信息
                            ListObjectsResponse listing = client.listObjects(listObjectsRequest);
            
                            // 遍历所有Object
                            for (BosObjectSummary objectSummary : listing.getContents()) {
                                System.out.println("ObjectKey: " + objectSummary.getKey());
                            }                	
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        }
                    }
                }).start();
            }}

            示例二:使用Nextmarker完整示例。

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.BosObjectSummary;
            import com.baidubce.services.bos.model.ListObjectsRequest;
            import com.baidubce.services.bos.model.ListObjectsResponse;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                     try {
                        BosClientConfiguration config = new BosClientConfiguration();
                        config.setCredentials(new DefaultBceCredentials(<AccessKeyId>, <SecretAccessKey>);
                        config.setEndpoint(<EndPoint>);
                        BosClient client = new BosClient(config);
                        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(<BucketName>);
                        listObjectsRequest.setMarker("");
                        listObjectsRequest.setMaxKeys(20);
                        listObjectsRequest.setDelimiter(BceConfig.BOS_DELIMITER);
                        ListObjectsResponse listObjectsResponse = client.listObjects(listObjectsRequest);
                        String nextMark = "";
                        if(listObjectsResponse.isTruncated()){
                           nextMark = listObjectsResponse.getNextMarker();
                        }
            
                       ListObjectsRequest listObjectsRequest2 = new ListObjectsRequest(<BucketName>);
                       listObjectsRequest2.setMarker(nextMark);
                       listObjectsRequest2.setMaxKeys(20);
                       listObjectsRequest2.setDelimiter(BceConfig.BOS_DELIMITER);
                       ListObjectsResponse listing = client.listObjects(listObjectsRequest2);
            
                       for (BosObjectSummary objectSummary : listing.getContents()) {
                           System.out.println("ObjectKey: " + objectSummary.getKey());
                        }                
            
                      } catch (BceServiceException e) {
                        System.out.println("Error ErrorCode: " + e.getErrorCode());
                        System.out.println("Error RequestId: " + e.getRequestId());
                        System.out.println("Error StatusCode: " + e.getStatusCode());
                        System.out.println("Error Message: " + e.getMessage());
                        System.out.println("Error ErrorType: " + e.getErrorType());
                     } catch (BceClientException e) {
                        System.out.println("Error Message: " + e.getMessage());
                     }
                  }
                }).start();
            }}

          查询模拟文件夹

          由于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>);
          
          // 递归列出fun文件夹下的所有文件
          listObjectsRequest.setPrefix("fun/");
          
          ListObjectsResponse listing = client.listObjects(listObjectsRequest);
          
          // 遍历所有Object
          System.out.println("Objects:");
          for (BosObjectSummary objectSummary : listing.getContents()) {
             System.out.println(objectSummary.getKey());
          }

          输出:

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

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

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

          // 构造ListObjectsRequest请求
          ListObjectsRequest listObjectsRequest = new ListObjectsRequest(<BucketName>);
          
          // 指定"/" 为模拟文件夹的分隔符
          listObjectsRequest.setDelimiter("/");
          
          // 列出fun文件夹下的所有文件和子文件夹
          listObjectsRequest.setPrefix("fun/");
          
          ListObjectsResponse listing = client.listObjects(listObjectsRequest);
          
          // 遍历所有Object
          System.out.println("Objects:");
          for (BosObjectSummary objectSummary : listing.getContents()) {
             System.out.println(objectSummary.getKey());
          }
          
          // 遍历所有CommonPrefix
          System.out.println("\nCommonPrefixs:");
          for (String commonPrefix : listing.getCommonPrefixes()) {
             System.out.println(commonPrefix);
          }

          输出:

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

          说明:

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

          获取Object

          简单的获取Object

          用户可以通过如下代码将Object读取到一个流中。

          • 基本流程

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

            // 获取Object,返回结果为BosObject对象
            BosObject object = client.getObject(<BucketName>, <ObjectKey>);
            
            // 获取ObjectMeta
            ObjectMetadata meta = object.getObjectMetadata();
            
            // 获取Object的输入流
            InputStream objectContent = object.getObjectContent();
            
            // 处理Object
            ...
            
            // 关闭流
            objectContent.close();

            注意:

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

            import java.io.BufferedReader;
            import java.io.IOException;
            import java.io.InputStream;
            import java.io.InputStreamReader;
            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.BosObject;
            import com.baidubce.services.bos.model.ObjectMetadata;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 获取Object,返回结果为BosObject对象
                            BosObject object = client.getObject(<BucketName>, <ObjectKey>);
            
                            // 获取ObjectMeta
                            ObjectMetadata meta = object.getObjectMetadata();
            
                            // 获取Object的输入流
                            InputStream objectContent = object.getObjectContent();
            
                            // 处理Object
                            FileOutputStream fos=new FileOutputStream(android.os.Environment.getExternalStorageDirectory()+"/1/file");  
                            byte[] buffer=new byte[<bufferSize>];  
                            int count=0;  
                            while ((count=objectContent.read(buffer))>=0) {  
                                fos.write(buffer,0,count);  
                            }  
            
                            System.out.println(meta.getETag());
                            System.out.println(meta.getContentLength());
            
                            // 关闭流
                            objectContent.close();
                            fos.close(); 
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }).start();
            }}

          通过GetObjectRequest获取Object

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

          • 基本流程

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

            // 新建GetObjectRequest
            GetObjectRequest getObjectRequest = new GetObjectRequest(<BucketName>, <ObjectKey>);
            
            // 获取0~100字节范围内的数据
            getObjectRequest.setRange(0, 100);
            
            // 获取Object,返回结果为BosObject对象
            BosObject object = client.getObject(getObjectRequest);

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

          获取下载进度

          用户可以通过回调函数获取到下载的进度信息。

          SDK提供的下载进度回调接口如下,您可以在其中定义在上传过程中您所需要的操作,如更新界面等等。

          public interface BceProgressCallback<T extends AbstractBceRequest> {
                    // request为下载的请求
                    // currentSize为当前下载的大小(单位:byte)
                    // totalSize为本次请求需要下载的总大小(单位:byte)
                    void onProgress(T request, long currentSize, long totalSize);
          • 示例代码

            GetObjectRequest request = new GetObjectRequest()
                    .withBucketName(this.bucketName)
                    .withKey(objectKey)
                    .withRange(0, 5);
            request.setProgressCallback(new BosProgressCallback<GetObjectRequest>() {
                @Override
                public void onProgress(GetObjectRequest request, long currentSize, long totalSize) {
                    Log.e(currentSize + "", totalSize + "");
                }
            });
            InputStream input = this.client.getObject(request).getObjectContent();

            注意: 下载进度接口与上传进度接口有所不同,无法指定每次回调时,下载量增长的片段大小。

          下载Object到指定路径

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

          • 基本流程

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

            // 新建GetObjectRequest
            GetObjectRequest getObjectRequest = new GetObjectRequest(<BucketName>, <ObjectKey>);
            
            // 下载Object到文件
            ObjectMetadata objectMetadata = client.getObject(getObjectRequest, new File("/path/to/file","w+"));

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

          获取Object的storageClass

          Object的storage class属性分为STANDARD(标准存储)、STANDARD_IA(低频存储)、COLD(冷存储)和ARCHIVE(归档存储)。

          示例代码

          public void getObjectStorageClass(){
            //...
          ObjectMetadata meta = client.getObjectMetadata(bucketName, key);
          String storageClass = meta.getStorageClass();
          }

          只获取ObjectMetadata

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

          示例代码

          ObjectMetadata objectMetadata = client.getObjectMetadata(<BucketName>, <ObjectKey>);

          获取Object的URL

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

          • 基本流程

            1. 创建BOSClient类的实例。
            2. 执行BOSClient.generatePresignedUrl( )方法。
            3. 返回一个Object的URL。
          • 示例代码

            URL url = client.generatePresignedUrl(<BucketName>, <ObjectKey>, <ExpirationInSeconds>);

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

          • 完整示例

            import java.net.URL;
            import android.app.Activity;
            import android.content.Intent;
            import android.net.Uri;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            
            public class ExampleActivity extends Activity {
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            //获取Object的URL
                            URL url = client.generatePresignedUrl(<BucketName>, <ObjectKey>, 2000);  
                            Uri uri = Uri.parse(url.toString());
                            Intent intent = new Intent(Intent.ACTION_VIEW, uri);
            
                            //执行URL
                            startActivity(intent);
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } 
                    }
                }).start();
            }}

          删除Object

          • 基本流程

            1. 创建BOSClient类的实例。
            2. 执行BOSClient.deleteObject()方法。
            3. 若操作失败后抛出异常,若成功无返回值。
          • 示例代码

            // 删除Object
            client.deleteObject(BucketName,ObjectKey);   //指定要删除的Object所在Bucket名称和该Object名称
          • 完整示例

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 删除Object
                            client.deleteObject(<BucketName>, <ObjectKey>);   //指定要删除的Object所在Bucket名称和该Object名称
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } 
                    }
                }).start();
            }}

          拷贝Object

          简单拷贝Object

          • 基本流程

            1. 创建BOSClient 类的实例。
            2. 执行BOSClient.copyObject( )方法。
            3. 返回CopyObjectResponse类实例,可通过getETag()/getLastModified()获取eTag和最后修改时间。
          • 示例代码

            // 拷贝Object
            CopyObjectResponse copyObjectResponse = client.copyObject(<SrcBucketName>, <SrcKey>, <DestBucketName>, <DestKey>);  //SrcBucketName, SrcKey为原地址,DestBucketName, DestKey为拷贝到的目的地址
            
            // 打印结果
            System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
          • 完整示例

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.CopyObjectResponse;
            
            public class ExampleActivity extends Activity {
            
            private String srcBucketName = <SrcBucketName>;
            private String srcKey = <SrcKey>;
            
            private String destBucketName = <DestBucketName>;
            private String destKey = <DestKey>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            // 拷贝Object
                            CopyObjectResponse copyObjectResponse = client.copyObject(<SrcBucketName>, <SrcKey>, <DestBucketName>, <DestKey>);
            
                            // 打印结果
                            System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } 
                    }
                }).start();
            }}

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

          通过CopyObjectRequest拷贝Object

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

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

            1. 创建CopyObjectRequest类的实例,传入<SrcBucketName>, <SrcKey>, <DestBucketName>, <DestKey>参数。
            2. 创建ObjectMetadata类的实例。
            3. 返回CopyObjectResponse类实例,可通过getETag()/getLastModified()获取eTag和最后修改时间。
          • 示例代码

            // 创建CopyObjectRequest对象
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(<SrcBucketName>, <SrcKey>, <DestBucketName>, <DestKey>);
            
            // 设置新的Metadata
            Map<String, String> userMetadata = new HashMap<String, String>();
            userMetadata.put(<UserMetaKey>,<UserMetaValue>);
            meta.setUserMetadata(userMetadata);
            copyObjectRequest.setNewObjectMetadata(meta);
            
            // 复制Object
            CopyObjectResponse copyObjectResponse = client.copyObject(copyObjectRequest);
            
            System.out.println("ETag: " + copyObjectResponse.getETag() + " LastModified: " + copyObjectResponse.getLastModified());

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

          Object的分块上传

          分块上传的场景

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

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

          Multipart Upload分块上传流程

          假设有一个文件,本地路径为 /path/to/file.zip ,由于文件比较大,使用分块上传其传输到BOS中。

          • 基本流程

            1. 初始化Multipart Upload。
            2. 上传分块。
            3. 完成分块上传。

          初始化Multipart Upload

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

          • 示例代码

            // 开始Multipart Upload
            InitiateMultipartUploadRequest initiateMultipartUploadRequest =
                  new InitiateMultipartUploadRequest(<BucketName>, <ObjectKey>);
            InitiateMultipartUploadResponse initiateMultipartUploadResponse =
                  client.initiateMultipartUpload(initiateMultipartUploadRequest);
            
            // 打印UploadId
            System.out.println("UploadId: " + initiateMultipartUploadResponse.getUploadId());

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

          上传分块

          将文件分块上传。

          • 示例代码

            // 设置每块为 5MB
            final long partSize = 1024 * 1024 * 5L;
            
            File partFile = new File("/path/to/file.zip");
            
            // 计算分块数目
            int partCount = (int) (partFile.length() / partSize);
            if (partFile.length() % partSize != 0) {
                partCount++;
            }
            // 新建一个List保存每个分块上传后的ETag和PartNumber
            List<PartETag> partETags = new ArrayList<PartETag>();
            // 获取文件流
            FileInputStream fis = new FileInputStream(partFile);
            for (int i = 0; i < partCount; i++) {
            
                // 计算每个分块的大小
                long skipBytes = partSize * i;
                long size = partSize < partFile.length() - skipBytes ?
                          partSize : partFile.length() - skipBytes;
            
                byte[] buf = new byte[(int)size];
                int offset = 0;
                while (true) {
                    int byteRead = fis.read(buf, offset, (int)size);
                    offset += byteRead;
                    if (byteRead < 0 || offset >= size) {
                       break;
                    }
                }
                ByteArrayInputStream bufStream = new ByteArrayInputStream(buf);
            
                // 创建UploadPartRequest,上传分块
                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(bucketName);
                uploadPartRequest.setKey(objectkey);
                uploadPartRequest.setUploadId(initiateMultipartUploadResponse.getUploadId());
                uploadPartRequest.setInputStream(bufStream);
                uploadPartRequest.setPartSize(size);
                uploadPartRequest.setPartNumber(i + 1);
                // 上传进度回调
                uploadPartRequest.setProgressCallback(new BosProgressCallback<UploadPartRequest>() {
                    @Override
                    public void onProgress(UploadPartRequest request, long currentSize, long totalSize) {
                        Log.e(currentSize + "", totalSize + "");
                    }
                });
            
                UploadPartResponse uploadPartResponse = client.uploadPart(uploadPartRequest);
            
                // 将返回的PartETag保存到List中。
                partETags.add(uploadPartResponse.getPartETag());
            
                System.out.println(uploadPartResponse.getPartETag());
              }
              // 关闭文件
              fis.close();

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

            • UploadPart 方法要求Part大小是1MB的整数倍或大于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>, <ObjectKey>, 
                        initiateMultipartUploadResponse.getUploadId(), partETags);
            
            // 完成分块上传
            CompleteMultipartUploadResponse completeMultipartUploadResponse =
                  client.completeMultipartUpload(completeMultipartUploadRequest);
            
            // 打印Object的ETag
            System.out.println(completeMultipartUploadResponse.getETag());

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

          • 完整示例

            import java.io.File;
            import java.io.FileInputStream;
            import java.io.IOException;
            import java.util.ArrayList;
            import java.util.List;
            import org.json.JSONException;
            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.CompleteMultipartUploadRequest;
            import com.baidubce.services.bos.model.CompleteMultipartUploadResponse;
            import com.baidubce.services.bos.model.InitiateMultipartUploadRequest;
            import com.baidubce.services.bos.model.InitiateMultipartUploadResponse;
            import com.baidubce.services.bos.model.PartETag;
            import com.baidubce.services.bos.model.UploadPartRequest;
            import com.baidubce.services.bos.model.UploadPartResponse;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;@Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                          BosClientConfiguration config = new BosClientConfiguration();
                          config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                          config.setEndpoint(<EndPoint>);
                          BosClient client = new BosClient(config);
            
                          // 开始Multipart Upload
                          InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(<BucketName>, <ObjectKey>);
                          InitiateMultipartUploadResponse initiateMultipartUploadResponse =
                                    client.initiateMultipartUpload(initiateMultipartUploadRequest);
            
                          // 打印UploadId
                          System.out.println("UploadId: " + initiateMultipartUploadResponse.getUploadId());
            
                          // 设置每块为 5MB
                          final long partSize = 1024 * 1024 * 5L;
            
                          File partFile = new File("/path/to/file.zip");
            
                          // 计算分块数目
                          int partCount = (int) (partFile.length() / partSize);
                          if (partFile.length() % partSize != 0) {
                              partCount++;
                          }
            
                          // 新建一个List保存每个分块上传后的ETag和PartNumber
                          List<PartETag> partETags = new ArrayList<PartETag>();
            
                          // 获取文件流
                          FileInputStream fis = new FileInputStream(partFile);
                          for (int i = 0; i < partCount; i++) {                       
            
                              // 计算每个分块的大小
                              long skipBytes = partSize * i;
                              long size = partSize < partFile.length() - skipBytes ?
                                      partSize : partFile.length() - skipBytes;
            
                              byte[] buf = new byte[(int)size];
                              int offset = 0;
                              while (true) {
                                  int byteRead = fis.read(buf, offset, (int)size);
                                  offset += byteRead;
                                  if (byteRead < 0 || offset >= size) {
                                      break;
                                  }
                              }
                              ByteArrayInputStream bufStream = new ByteArrayInputStream(buf);
            
                              // 创建UploadPartRequest,上传分块
                              UploadPartRequest uploadPartRequest = new UploadPartRequest();
                              uploadPartRequest.setBucketName(<BucketName>);
                              uploadPartRequest.setKey(<ObjectKey>);
                              uploadPartRequest.setUploadId(initiateMultipartUploadResponse.getUploadId());
                              uploadPartRequest.setInputStream(fis);
                              uploadPartRequest.setPartSize(size);
                              uploadPartRequest.setPartNumber(i + 1);
                              UploadPartResponse uploadPartResponse = client.uploadPart(uploadPartRequest);
            
                              // 将返回的PartETag保存到List中。
                              partETags.add(uploadPartResponse.getPartETag());
            
                              System.out.println(uploadPartResponse.getPartETag());                                         
                          }
                          // 关闭文件
                          fis.close();
            
                          CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(<BucketName>, <ObjectKey>, initiateMultipartUploadResponse.getUploadId(), partETags);
            
                          // 完成分块上传
                          CompleteMultipartUploadResponse completeMultipartUploadResponse =
                                  client.completeMultipartUpload(completeMultipartUploadRequest);
            
                          // 打印Object的ETag
                          System.out.println(completeMultipartUploadResponse.getETag());
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error Message: " + e.getMessage());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (JSONException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } 
                    }
                }).start();
            }}

          取消分块上传

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

          • 示例代码

            AbortMultipartUploadRequest abortMultipartUploadRequest =
                new AbortMultipartUploadRequest(<BucketName>, <ObjectKey>, <UploadId>);
            
            // 取消分块上传
            client.abortMultipartUpload(abortMultipartUploadRequest);

          获取未完成的分块上传

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

          • 基本流程

            1. 创建listMultipartUploadsRequest类的实例,传入<BucketName>参数。
            2. 创建BOSClient类的实例,执行BOSClient.listMultipartUploads( )方法。
            3. listMultipartUploads()返回所有已上传part的信息。
          • 示例代码

            ListMultipartUploadsRequest listMultipartUploadsRequest = 
                new ListMultipartUploadsRequest(<BucketName>);
            
            // 获取Bucket内所有上传事件
            ListMultipartUploadsResponse list = client.listMultipartUploads(listMultipartUploadsRequest);// 遍历所有上传事件
            for (MultipartUploadSummary multipartUpload : list.getMultipartUploads()) {
                System.out.println("Key: " + multipartUpload.getKey() + " UploadId: " + multipartUpload.getUploadId());
            }

            注意:

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

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.ListMultipartUploadsRequest;
            import com.baidubce.services.bos.model.ListMultipartUploadsResponse;
            import com.baidubce.services.bos.model.MultipartUploadSummary;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            ListMultipartUploadsRequest listMultipartUploadsRequest = 
                                    new ListMultipartUploadsRequest(<BucketName>);
            
                                // 获取Bucket内所有上传事件
                            ListMultipartUploadsResponse listing = client.listMultipartUploads(listMultipartUploadsRequest);
            
                             // 遍历所有上传事件
                             for (MultipartUploadSummary multipartUpload : listing.getMultipartUploads()) {
                                 System.out.println("Key: " + multipartUpload.getKey() + " UploadId: " + multipartUpload.getUploadId());
                             }
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } 
                    }
                }).start();
            }}

          获取所有已上传的分块信息

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

          • 基本流程

            1. 创建ListPartsRequest类的实例,传入<BucketName>,<ObjectKey>, <UploadId>参数。
            2. 创建BOSClient类的实例,执行BOSClient.listParts( )方法。
            3. listParts()返回所有已上传part的信息。
          • 示例代码

            ListPartsRequest listPartsRequest = new ListPartsRequest(<BucketName>, <ObjectKey>, <UploadId>);// 获取上传的所有Part信息
            ListPartsResponse partListing = client.listParts(listPartsRequest);// 遍历所有Part
            for (PartSummary part : partListing.getParts()) {
                System.out.println("PartNumber: " + part.getPartNumber() + " ETag: " + part.getETag());
            }

            注意:

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

            import android.app.Activity;
            import android.os.Bundle;
            import com.baidubce.BceClientException;
            import com.baidubce.BceServiceException;
            import com.baidubce.auth.DefaultBceCredentials;
            import com.baidubce.demo.R;
            import com.baidubce.services.bos.BosClient;
            import com.baidubce.services.bos.BosClientConfiguration;
            import com.baidubce.services.bos.model.ListPartsRequest;
            import com.baidubce.services.bos.model.ListPartsResponse;
            import com.baidubce.services.bos.model.PartSummary;
            
            public class ExampleActivity extends Activity {
            
            private String bucketName = <BucketName>;
            private String objectKey = <ObjectKey>;
            private String uploadId = <UploadId>;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            BosClientConfiguration config = new BosClientConfiguration();
                            config.setCredentials(new DefaultBceCredentials(<AccessKeyID>, <SecretAccessKey>));
                            config.setEndpoint(<EndPoint>);
                            BosClient client = new BosClient(config);
            
                            ListPartsRequest listPartsRequest = new ListPartsRequest(<BucketName>, <ObjectKey>, <UploadId>);
                            listPartsRequest.setMaxParts(100);
                            listPartsRequest.setPartNumberMarker(50);
            
                             // 获取上传的所有Part信息
                             ListPartsResponse partListing = client.listParts(listPartsRequest);
            
                             // 遍历所有Part
                             for (PartSummary part : partListing.getParts()) {
                                 System.out.println("PartNumber: " + part.getPartNumber() + " ETag: " + part.getETag());
                             }
            
                        } catch (BceServiceException e) {
                            System.out.println("Error ErrorCode: " + e.getErrorCode());
                            System.out.println("Error RequestId: " + e.getRequestId());
                            System.out.println("Error StatusCode: " + e.getStatusCode());
                            System.out.println("Error ErrorType: " + e.getErrorType());
                            System.out.println("Error Message: " + e.getMessage());
                        } catch (BceClientException e) {
                            System.out.println("Error Message: " + e.getMessage());
                        } 
                    }
                }).start();
            }}

          封装分块上传

          在Android SDK中,Bos为用户提供了putSuperObjectFromFile接口,它对分块上传涉及到的initiateMultipartUpload、UploadPart、completeMultipartUpload三个方法进行封装,用户只需调用该接口即可完成分块上传,同时,支持进度同步回调。

          • 简单示例:

            File file = new File("/path/to/file.zip");
            PutSuperObjectRequest request = new PutSuperObjectRequest(bucketName, objectKey, file);
            bosClient.putSuperObjectFromFile(request);
          • 示例:设置分块大小为2MB,线程数为4,并且每1024个byte同步进度回调

            BosClientConfiguration config=new BosClientConfiguration();
            config.setUploadSegmentPart(1024);
            File file = new File("/path/to/file.zip");
            PutSuperObjectRequest request = new PutSuperObjectRequest(bucketName, objectKey,
                                                                      file, 1024 * 1024 * 2L, 4);
            request.setProgressCallback(new BosProgressCallback<PutSuperObjectRequest>() {
                @Override
                public void onProgress(PutSuperObjectRequest request, long currentSize, long totalSize) {
                    Log.e(currentSize + "", totalSize + "");
                }
            });
            bosClient.putSuperObjectFromFile(request);

          注意:

          • 默认情况下,分块大小是5MB,线程数是5,进度回调周期是每2048个byte。
          • 若一个大文件耗时很长,用户想结束分块上传,可调用PutSuperObjectRequest中的cancel()方法。
          上一篇
          Bucket管理
          下一篇
          日志