Skip to content

baidubce/bce-sdk-ruby

Repository files navigation

BOS Ruby SDK文档

概述

本文档主要介绍BOS Ruby SDK的安装和使用。在使用本文档前,您需要先了解BOS的一些基本知识,并已开通了BOS服务。若您还不了解BOS,可以参考产品描述入门指南

安装SDK工具包

运行环境

Ruby SDK包要求运行环境至少为Ruby 2.0 版本。

安装SDK

方式一:通过gem安装

gem install baidubce-sdk

方式二:通过bundler安装

  1. 首先得确认安装了bundler,安装命令:gem install bundler
  2. 在你的应用程序的Gemfile中添加:gem 'baidubce-sdk', '~> 0.9.0',再运行bundle install

说明: 用户在安装好gem之后,可以输入irb进入Ruby交互式命令行,输入require 'baidubce/services/bos/bos_client',如果显示"true"则SDK已经顺利安装。github源码链接

SDK目录结构

│──baidubce-sdk.gemspec         //依赖的第三方gem 
├──lib
│   └── baidubce
│       ├── auth                //BCE签名相关
│       ├── http                //BCE的http通信相关
│       ├── services
│       │   └── bos                   //BOS主目录
│       │       ├── bos_client.rb     //BOS操作类,所有操作可以通过BosClient类可以完成
│       │       ├── bos_constants.rb  //BOS常量
│       │   └── sts                   //STS主目录
│       │       ├── sts_client.rb     //STS操作类
│       ├── exception.rb              //BCE客户端的异常
│       ├── retry_policy.rb           //BCE客户端重试机制
│       ├── bce_base_client.rb        //BCE公用客户端
│       └── utils                //BCE公用工具 
└──samples                      //使用示例

卸载SDK

卸载SDK时,执行gem uninstall baidubce-sdk,删除脚本中require和include语句即可。

初始化

确认Endpoint

  • 在确认您使用SDK时配置的Endpoint时,可先阅读开发人员指南中关于BOS访问域名的部分,理解Endpoint相关的概念。

  • 百度云目前开放了多区域支持,请参考区域选择说明

  • 目前支持“华北-北京”、“华南-广州”和“华东-苏州”三个区域。北京区域:http://bj.bcebos.com,广州区域:http://gz.bcebos.com,苏州区域:http://su.bcebos.com

    对应信息为:

    访问区域 对应Endpoint
    BJ bj.bcebos.com
    GZ gz.bcebos.com
    SU su.bcebos.com

获取密钥

要使用百度云BOS,您需要拥有一个有效的 AK(Access Key ID)和SK(Secret Access Key)用来进行签名认证。AK/SK是由系统分配给用户的,均为字符串,用于标识用户,为访问BOS做签名验证。

可以通过如下步骤获得并了解您的AK/SK信息:

  1. 注册百度云账号
  2. 创建AK/SK

新建BosClient

BosClient是BOS服务的客户端,为开发者与BOS服务进行交互提供了一系列的方法。

使用AK/SK新建BosClient

通过AK/SK方式访问BOS,用户可以参考如下代码新建一个BosClient:

#使用Ruby SDK,引入bos_client和Baidubce模块
require 'baidubce/services/bos/bos_client'
include Baidubce

#配置client参数
credentials = Auth::BceCredentials.new(
    "accessKeyId",
    "secretAccessKey"
)

conf = BceClientConfiguration.new(
    credentials,
    "ENDPOINT"
)
#新建BosClient
client = Services::BosClient.new(conf)

注意:

  1. 在上面代码中,accessKeyId对应控制台中的“Access Key ID”,secretAccessKey对应控制台中的“Access Key Secret”,获取方式请参考《操作指南 管理ACCESSKEY》。
  2. 如果用户需要自己指定域名,可以通过传入ENDPOINT参数来指定,ENDPOINT参数需要用指定区域的域名来进行定义,如服务所在区域为北京,则为http://bj.bcebos.com

使用STS创建BosClient

申请STS token

BOS可以通过STS机制实现第三方的临时授权访问。STS(Security Token Service)是百度云提供的临时授权服务。通过STS,您可以为第三方用户颁发一个自定义时效和权限的访问凭证。第三方用户可以使用该访问凭证直接调用百度云的API或SDK访问百度云资源。

通过STS方式访问BOS,用户需要先通过STS的client申请一个认证字符串,申请方式可参见百度云STS使用介绍

用STS token新建BOSClient

申请好STS后,可将STStoken配置到BosClient中,用户可以参考如下代码新建一个BosClient:

  1. 首先进行STS的endpoint配置。STS的配置示例如下:

    require 'baidubce/services/sts/sts_client'
    require 'baidubce/services/bos/bos_client'
    
    credentials = Baidubce::Auth::BceCredentials.new(
        "your ak",
        "your sk"
    )
    
    sts_conf = Baidubce::BceClientConfiguration.new(
        credentials,
        "http://sts.bj.baidubce.com"
    )
    
  2. StsClient的示例代码如下:

    # 新建StsClient
    sts_client = Baidubce::Services::StsClient.new(sts_conf)
    acl = {
                id: 'aaaaaaaaaaaaaaaaaaaaaaaaaa',
                accessControlList: [
                    {
                        eid: 'shj',
                        service: 'bce:bos',
                        region: 'bj',
                        effect: 'Allow',
                        resource: ["bos-demo"],
                        permission: ["READ"]
                    }
                ]
    }
    
    # durationSeconds为失效时间,如果为非int值或者不设置该参数,会使用默认的12小时作为失效时间
    # sts_client.get_session_token(acl, "test")
    # sts_client.get_session_token(acl, 1024)
    sts_response = sts_client.get_session_token(acl)
    
    sts_ak = sts_response["accessKeyId"]
    sts_sk = sts_response['secretAccessKey']
    token = sts_response['sessionToken']
    

    **注意:**其中acl指用户定义的acl,语法请参照访问控制

  3. 将获取到的accessKeyID/secretAccessKey/sessionToken用于新建BosClient。

     # 使用获取到的ak, sk, token新建BosClient访问BOS
    sts_credentials = Baidubce::Auth::BceCredentials.new(
        sts_ak,
        sts_sk,
        token
    )
    
    conf = Baidubce::BceClientConfiguration.new(
        sts_credentials,
        "http://bj.bcebos.com",
    )
    
    client = Baidubce::Services::BosClient.new(conf)
    

    **注意:**目前使用STS配置client时,无论对应BOS服务的endpoint在哪里,endpoint都需配置为http://sts.bj.baidubce.com

配置HTTPS协议访问BOS

BOS支持HTTPS传输协议,您可以通过如下两种方式在BOS Ruby SDK中使用HTTPS访问BOS服务:

  • endpoint中指定HTTPS:

    # 配置client参数
    credentials = Auth::BceCredentials.new(
        "accessKeyId",
        "secretAccessKey"
    )
    
    conf = BceClientConfiguration.new(
        credentials,
        "https://bj.bcebos.com"
    )
    # 新建BosClient
    client = Services::BosClient.new(conf)
    
  • 通过在protocol中指定https来设置HTTPS协议:

    # 配置client参数
    credentials = Auth::BceCredentials.new(
        "accessKeyId",
        "secretAccessKey"
    )
    
    options = {
        'protocol' => 'https'
    }
    
    conf = BceClientConfiguration.new(
        credentials,
        "bj.bcebos.com",
        options
    )
    
    # 新建BosClient
    client = Services::BosClient.new(conf)
    

    **注意:**如果您在指定了endpoint的scheme的同时指定了protocol参数,则以endpoint为准。

配置BosClient

设置自定义参数

Ruby SDK默认设置了一些基本参数,若用户想要对参数的值进行修改,可以创建自身的参数配置,并在构造BosClient的时候传入,传入代码参考如下:

#配置自定义参数
options = {
    'protocol' => 'https',
    'read_timeout_in_millis' => 1000 * 60,
    'region' => 'bj'
}

conf = BceClientConfiguration.new(
    credentials,
    "http://bj.bcebos.com",
    options
)

#新建BosClient
client = Services::BosClient.new(conf)

参数说明如下:

参数 说明 默认值
protocol 协议 http
region 区域 bj
open_timeout_in_millis 请求超时时间(单位:毫秒) 50 * 1000
read_timeout_in_millis 通过打开的连接传输数据的超时时间(单位:毫秒) 10 * 60 * 1000(设置时需要对文件大小和网速进行评估,否则上传大文件时会产生超时)
send_buf_size 发送缓冲区大小 1024 * 1024
recv_buf_size 接收缓冲区大小 10 * 1024 * 1024

设置可选参数

BosClient将可选的参数封装到options中,每一个方法具有的可选参数详见具体的接口使用方法介绍,现以put_object_from_string方法为例,参考如下代码实现设置可选参数:

# 利用options在上传Object的时候传入指定参数
user_metadata = { "key1" => "value1" }
options = { Http::CONTENT_TYPE => 'string',
            "key2" => "value2",
            'Content-Disposition' => 'inline',
            'user-metadata' => user_metadata
}

client.put_object_from_string(bucket_name, object_name, "obj_str", options)

Bucket管理

Bucket既是BOS上的命名空间,也是计费、权限控制、日志记录等高级功能的管理实体。

  • Bucket名称在所有区域中具有全局唯一性,且不能修改。

    说明:

    • 百度云目前开放了多区域支持,请参考区域选择说明
    • 目前支持“华北-北京”、“华南-广州”和“华东-苏州”三个区域。北京区域:http://bj.bcebos.com,广州区域:http://gz.bcebos.com,苏州区域:http://su.bcebos.com
  • 存储在BOS上的每个Object都必须包含在一个Bucket中。

  • 一个用户最多可创建100个Bucket,但每个Bucket中存放的Object的数量和大小总和没有限制,用户不需要考虑数据的可扩展性。

Bucket权限管理

设置Bucket的访问权限

如下代码将Bucket的权限设置为了private:

client.set_bucket_canned_acl(bucket_name, "private")

canned acl支持三种权限,分别为:privatepublic-readpublic-read-write。关于权限的具体内容可以参考《BOS API文档 使用CannedAcl方式的权限控制》。

设置指定用户对Bucket的访问权限

BOS提供set_bucket_acl方法来实现指定用户对Bucket的访问权限设置,可以参考如下代码实现:

acl = [{'grantee' => [{'id' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'},
                      {'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}],
        'permission' => ['FULL_CONTROL']
}]

client.set_bucket_acl(bucket_name, acl)

注意:

  1. permission中的权限设置包含三个值:READWRITEFULL_CONTROL,它们分别对应相关权限。具体内容可以参考《BOS API文档 [上传ACL文件方式的权限控制](API.html# 上传ACL文件方式的权限控制)》。
  2. 设置两个以上(含两个)被授权人时,请参考以上示例的格式,若将数组合并会返回报错。

设置更多Bucket访问权限

  1. 通过设置referer白名单方式设置防盗链

    acl = [{'grantee' => [{'id' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'},
                          {'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}],
            'permission' => ['FULL_CONTROL'],
            'condition' => {
                'referer' => {
                    'stringLike' => ['http://www.abc.com/*'],
                    'stringEquals' => ['http://www.abc.com']
                 }
            }
    }]
    
    client.set_bucket_acl(bucket_name, acl)
    
  2. 限制客户端IP访问,只允许部分客户端IP访问

    acl = [{'grantee' => [{'id' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'},
                          {'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}],
            'permission' => ['FULL_CONTROL'],
            'condition' => {
                "ipAddress" => [
                      '192.168.0.0/16',
                      '192.169.0.*',
                      '192.170.0.5'
                ]
            }
    }]
    
    client.set_bucket_acl(bucket_name, acl)
    

设置STS临时token权限

对于通过STS方式创建的临时访问身份,管理员也可进行专门的权限设定。 STS的简介及设置临时权限的方式可参见临时授权访问

使用BOS Ruby SDK设置STS临时token权限可参考使用STS创建BosClient

查看Bucket的权限

如下代码可以查看Bucket的权限:

client.get_bucket_acl(bucket_name)

get_bucket_acl方法返回的解析类中可供调用的参数有:

参数 说明
owner Bucket owner信息
id Bucket owner的用户ID
acl 标识Bucket的权限列表
grantee 标识被授权人
-id 被授权人ID
permission 标识被授权人的权限

查看Bucket所属的区域

Bucket Location即Bucket Region,百度云支持的各region详细信息可参见区域选择说明

如下代码可以获取该Bucket的Location信息:

client.get_bucket_location(bucket_name)

新建Bucket

如下代码可以新建一个Bucket:

bucketName = "your_bucket";

# Bucket是否存在,若不存在创建Bucket
client.create_bucket(bucket_name) unless client.does_bucket_exist(bucket_name)

注意: 由于Bucket的名称在所有区域中是唯一的,所以需要保证bucketName不与其他所有区域上的Bucket名称相同。

Bucket的命名有以下规范:

  • 只能包括小写字母,数字,短横线(-)。
  • 必须以小写字母或者数字开头。
  • 长度必须在3-63字节之间。

通过上述代码创建的bucket,权限是私有读写,存储类型是标准类型(Standard)。用户在控制台创建Bucket时可以指定Bucket权限和存储类型。

列举Bucket

如下代码可以列出用户所有的Bucket:

buckets = client.list_buckets()

删除Bucket

删除指定Bucket

如下代码可以删除一个Bucket:

bucketName = "your_bucket";
client.delete_bucket(bucketName)

注意:

  • 在删除前需要保证此Bucket下的所有Object和未完成的三步上传Part已经被删除,否则会删除失败。
  • 在删除前确认该Bucket没有开通跨区域复制,不是跨区域复制规则中的源Bucket或目标Bucket,否则不能删除。

删除所有Bucket

delete_bucketlist_buckets函数结合,可以删除全部Bucket,参考代码如下:

# 列出全部Bucket
buckets = client.list_buckets()['buckets']

# 遍历删除全部Bucket
buckets.each do |bucket|
    while true
        options = {}
        res = client.list_objects(bucket['name'], options)
        res['contents'].each do |object|
            client.delete_object(bucket['name'], object['key'])
        end
        if res['isTruncated']
            options[:marker] = res['nextMarker']
        else
            break
        end
    end
    client.delete_bucket(bucket['name'])
end

判断Bucket是否存在

若用户需要判断某个Bucket是否存在,则如下代码可以做到:

client.does_bucket_exist(bucketName)

文件管理

上传文件

在BOS中,用户操作的基本数据单元是Object。Object包含Key、Meta和Data。其中,Key是Object的名字;Meta是用户对该Object的描述,由一系列Name-Value对组成;Data是Object的数据。

BOS Ruby SDK提供了丰富的文件上传接口,可以通过以下方式上传文件:

  • 简单上传
  • 追加上传
  • 分片上传
  • 断点续传上传

简单上传

BOS在简单上传的场景中,支持以指定文件形式、以数据流方式、以二进制串方式、以字符串方式执行Object上传,请参考如下代码:

# 以数据流形式上传Object
client.put_object(bucket_name, object_name, data)

# 从字符串中上传Object
client.put_object_from_string(bucket_name, object_name, "string")

# 从文件中直接上传Object
client.put_object_from_file(bucket_name, object_name, file_path)

Object以文件的形式上传到BOS中,putObject相关接口支持不超过5GB的Object上传。在PutObject请求处理成功后,BOS会在Header中返回Object的ETag作为文件标识。

设置文件元信息

文件元信息(Object Meta),是对用户在向BOS上传文件时,同时对文件进行的属性描述,主要分为分为两种:设置HTTP标准属性(HTTP Headers)和用户自定义的元信息。

设定Object的Http Header

BOS Ruby SDK本质上是调用后台的HTTP接口,因此用户可以在上传文件时自定义Object的Http Header。常用的http header说明如下:

名称 描述 默认值
Content-MD5 文件数据校验,设置后BOS会启用文件内容MD5校验,把您提供的MD5与文件的MD5比较,不一致会抛出错误
Content-Type 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如没有指,BOS则根据文件的扩展名自动生成,如文件没有扩展名则填默认值 application/octet-stream
Content-Disposition 指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称
Content-Length 上传的文件的长度,超过流/文件的长度会截断,不足为实际值 流/文件时间长度
Expires 缓存过期时间
Cache-Control 指定该Object被下载时的网页的缓存行为

参考代码如下:

options = { Http::CONTENT_TYPE => 'string',
            Http::CONTENT_MD5 => 'md5',
            Http::CONTENT_DISPOSITION => 'inline',
            'key1' => 'value1'
}

client.put_object_from_string(bucket_name, object_name, "string", options)

用户自定义元信息

BOS支持用户自定义元数据来对Object进行描述。如下代码所示:

options = { 
            'user-metadata' => { "key1" => "value1" }
}

client.put_object_from_string(bucket_name, object_name, "string", options)

提示:

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

上传Object时设置存储类型

BOS支持标准存储, 低频存储和冷存储,上传Object并存储为低频存储类型通过指定StorageClass实现,三种存储类型对应的参数如下:

存储类型 参数
标准存储 STANDRAD
低频存储 STANDARD_IA
冷存储 COLD

以低频存储为例,代码如下:

# 上传一个低频object(默认为标准object)
client.put_object_from_file(bucket_name, object_name, file_path, Http::BOS_STORAGE_CLASS => 'STANDARD_IA')

putObject请求处理成功后,BOS会在Header中返回Object的Content-MD5,用户可以根据这个参数来对文件进行校验。

追加上传

上文介绍的简单上传方式,创建的Object都是Normal类型,用户不可再进行追加写,这在日志、视频监控、视频直播等数据复写较频繁的场景中使用不方便。

正因如此,百度云BOS特别支持了AppendObject,即以追加写的方式上传文件。通过AppendObject操作创建的Object类型为Appendable Object,可以对该Object追加数据。AppendObject大小限制为0~5G。

通过AppendObject方式上传示例代码如下:

# 从字符串上传一个appendable object
client.append_object_from_string(bucket_name, object_name, "string")

# 从offset处开始追加写
client.append_object_from_string(bucket_name, object_name, "append_str", 'offset' => 6)

分块上传

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

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

下面将一步步介绍Multipart Upload的实现。假设有一个文件,本地路径为 /path/to/file.zip ,由于文件比较大,将其分块传输到BOS中。

初始化Multipart Upload

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

upload_id = client.initiate_multipart_upload(bucket_name, object_name)["uploadId"]

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

上传低频存储类型Object的初始化

初始化低频存储的一个分块上传事件:

options = { 
            Http::BOS_STORAGE_CLASS => 'STANDARD_IA'
}
client.initiate_multipart_upload(bucket_name, object_name, options)

上传冷存储类型Object的初始化

初始化冷存储的一个分块上传事件:

options = { 
            Http::BOS_STORAGE_CLASS => 'COLD'
}
client.initiate_multipart_upload(bucket_name, object_name, options)

上传分块

接着,把文件分块上传。

# 设置分块的开始偏移位置
left_size = File.open(multi_file, "r").size()
offset = 0
part_number = 1
part_list = []

while left_size > 0 do
    part_size = 5 * 1024 * 1024
    if left_size < part_size
        part_size = left_size
    end

    response = client.upload_part_from_file(
        bucket_name, object_name, upload_id, part_number, part_size, multi_file, offset)
    left_size -= part_size
    offset += part_size
    # your should store every part number and etag to invoke complete multi-upload
    part_list << {
        "partNumber" => part_number,
        "eTag" => response['etag']
    }
    part_number += 1
end

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

  • UploadPart 方法要求除最后一个Part以外,其他的Part大小都要大于等于5MB。但是Upload Part接口并不会立即校验上传Part的大小;只有当Complete Multipart Upload的时候才会校验。
  • 为了保证数据在网络传输过程中不出现错误,建议您在UploadPart后,使用每个分块BOS返回的Content-MD5值分别验证已上传分块数据的正确性。当所有分块数据合成一个Object后,不再含MD5值。
  • Part号码的范围是1~10000。如果超出这个范围,BOS将返回InvalidArgument的错误码。
  • 每次上传Part时都要把流定位到此次上传块开头所对应的位置。
  • 每次上传Part之后,BOS的返回结果会包含eTagpartNumber,需要保存到part_list中。part_list类型是array,里面每个元素是个hash,每个hash包含两个关键字,一个是partNumber, 一个是eTag;在后续完成分块上传的步骤中会用到它。

完成分块上传

如下代码所示,完成分块上传:

client.complete_multipart_upload(bucket_name, object_name, upload_id, part_list)

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

取消分块上传

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

client.abort_multipart_upload(bucket_name, object_name, upload_id)

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

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

response = client.list_multipart_uploads(bucket_name)
puts response['bucket']
puts response['uploads'][0]['key']

注意:

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

获取所有已上传的块信息

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

response = client.list_parts(bucket_name, object_name, upload_id)
puts response['bucket']
puts response['uploads'][0]['key']

注意:

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

断点续传上传

当用户向BOS上传大文件时,如果网络不稳定或者遇到程序崩等情况,则整个上传就失败了,失败前已经上传的部分也作废,用户不得不重头再来。这样做不仅浪费资源,在网络不稳定的情况下,往往重试多次还是无法完成上传。 基于上述场景,BOS提供了断点续传上传的能力:

  • 当网络情况一般的情况下,建议使用三步上传方式,将object分为1Mb的块,参考分块上传
  • 当您的网络情况非常差,推荐使用appendObject的方式进行断点续传,每次append 较小数据256kb,参考[追加上传](# 追加上传)。

提示

  • 断点续传是分片上传的封装和加强,是用分片上传实现的;
  • 文件较大或网络环境较差时,推荐使用分片上传;

下载文件

BOS Ruby SDK提供了丰富的文件下载接口,用户可以通过以下方式从BOS中下载文件:

  • 简单流式下载
  • 下载到本地文件
  • 断点续传下载
  • 范围下载

简单流式下载

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

client.get_object_as_string(bucket_name, object_name)

直接下载Object到文件

用户可以参考如下代码将Object下载到指定文件:

client.get_object_to_file(bucket_name, object_name, file_name)

范围下载

为了实现更多的功能,可以通过配置RANGE参数来指定下载范围,实现更精细化地获取Object。如果指定的下载范围是0 - 100,则返回第0到第100个字节的数据,包括第100个,共101字节的数据,即[0, 100]。RANGE参数的格式为array(offset, endset)其中两个变量为长整型,单位为字节。用户也可以用此功能实现文件的分段下载和断点续传。

range = [0,100]
client.get_object_as_string(bucket_name, object_name, range)

其他使用方法

获取Object的存储类型

Object的storage class属性分为STANDARD(标准存储), STANDARD_IA(低频存储)和COLD(冷存储),通过如下代码可以实现:

response = client.get_object_meta_data(bucket_name, object_name)
puts response[Http::BOS_STORAGE_CLASS];

只获取ObjectMetadata

用户也可通过get_object_meta_data方法可以只获取ObjectMetadata而不获取Object的实体。如下代码所示:

response = client.get_object_meta_data(bucket_name, object_name)
puts response['etag'];

get_object_meta_data方法返回的解析类中可供调用的参数有:

参数 说明
content-type Object的类型
content-length Object的大小
content-md5 Object的MD5
etag Object的HTTP协议实体标签
x-bce-storage-class Object的存储类型
user-metadata 如果在PutObject指定了userMetadata自定义meta,则返回此项

变更文件存储等级

上文中已提到,BOS支持为文件赋予STANDARD(标准存储), STANDARD_IA(低频存储)和COLD(冷存储)三种存储类型。同时,BOS Ruby SDK也支持用户对特定文件执行存储类型变更的操作。

涉及到的参数如下:

参数 说明
x-bce-storage-class 指定Object的存储类型,STANDARD_IA代表低频存储,COLD代表冷存储,不指定时默认是标准存储类型。

示例如下:

options = { 
            Http::BOS_STORAGE_CLASS => 'STANDARD_IA'
}

# 标准存储转低频存储
client.copy_object(bucket_name, object_name, bucket_name, object_name, options)
puts client.get_object_meta_data(bucket_name, object_name)[Http::BOS_STORAGE_CLASS]

options = { 
            Http::BOS_STORAGE_CLASS => 'COLD'
}

# 低频存储转冷存储
client.copy_object(bucket_name, object_name, bucket_name, object_name, options)
puts client.get_object_meta_data(bucket_name, object_name)[Http::BOS_STORAGE_CLASS]

获取文件下载URL

用户可以参考如下代码获取Object的URL:

options = { 'expiration_in_seconds' => 360,
            'timestamp' => Time.now.to_i
}

puts client.generate_pre_signed_url(bucket_name, object_name, options)

说明:

  • 用户在调用该函数前,需要手动设置endpoint为所属区域域名。百度云目前开放了多区域支持,请参考区域选择说明。目前支持“华北-北京”、“华南-广州”和“华东-苏州”三个区域。北京区域:http://bj.bcebos.com,广州区域:http://gz.bcebos.com,苏州区域:http://su.bcebos.com
  • EXPIRATION_IN_SECONDS为指定的URL有效时长,时间从当前时间算起,为可选参数,不配置时系统默认值为1800秒。如果要设置为永久不失效的时间,可以将expiration_in_seconds参数设置为 -1,不可设置为其他负数。
  • TIMESTAMP为可选参数,不配置时,系统默认TIMESTAMP为当前时间。
  • 如果预期获取的文件时公共可读的,则对应URL链接可通过简单规则快速拼接获取: http://bucketName.$region.bcebos.com/$bucket/$object

列举存储空间中的文件

BOS SDK支持用户通过以下两种方式列举出object:

  • 简单列举
  • 通过参数复杂列举

除此之外,用户还可在列出文件的同时模拟文件夹

简单列举

当用户希望简单快速列举出所需的文件时,可通过listObjects方法获取Bucket中的Object列表。

client.list_objects(bucket_name)

注意:

  1. 默认情况下,如果Bucket中的Object数量大于1000,则只会返回1000个Object。
  2. 若想增大返回Object的数目,可以使用Marker参数分次读取。

通过参数复杂列举

除上述简单列举外,用户还可通过options配置可选参数来实现各种灵活的查询功能。可设置的参数如下:

参数 功能
PREFIX 限定返回的object key必须以prefix作为前缀
DELIMITER 是一个用于对Object名字进行分组的字符所有名字包含指定的前缀且第一次出现。Delimiter字符之间的Object作为一组元素: CommonPrefixes
MARKER 设定结果从marker之后按字母排序的第一个开始返回
MAX_KEYS 限定此次返回object的最大数,如果不设定,默认为100,max-keys取值不能大于1000

注意:

  1. 如果有Object以Prefix命名,当仅使用Prefix查询时,返回的所有Key中仍会包含以Prefix命名的Object,详见递归列出目录下所有文件
  2. 如果有Object以Prefix命名,当使用Prefix和Delimiter组合查询时,返回的所有Key中会有Null,Key的名字不包含Prefix前缀,详见[查看目录下的文件和子目录](# 查看目录下的文件和子目录)。

下面我们分别以几个案例说明通过参数列举的方法:

指定最大返回条数

# 指定最大返回条数为500
options = { 
            maxKeys: 500
}
puts client.list_objects(bucket_name, options)

返回指定前缀的object

# 指定返回前缀为usr的object
options = { 
            prefix: 'usr'
}
puts client.list_objects(bucket_name, options)

从指定Object后返回

# 用户可以定义不包括某object,从其之后开始返回
options = { 
            marker: 'object'
}
puts client.list_objects(bucket_name, options)

分页获取所有Object

用户可设置每页最多500条记录

options = { 
            maxKeys: 500
}

is_truncated = true
while is_truncated 
    res = client.list_objects(bucket_name, options)
    is_truncated = res['isTruncated']
    options[:marker] = res['nextMarker'] unless res['nextMarker'].nil?
end

分页获取所有特定Object后的结果

用户可设置每页最多500条记录,并从某特定object之后开始获取

options = { 
            maxKeys: 5,
            marker: 'object'
}

is_truncated = true
while is_truncated 
    res = client.list_objects(bucket_name, options)
    is_truncated = res['isTruncated']
    options[:marker] = res['nextMarker'] unless res['nextMarker'].nil?
end

listObjects方法返回的解析类中可供调用的参数有:

参数 说明
name Bucket名称
prefix 匹配以prefix开始到第一次出现Delimiter字符之间的object作为一组元素返回
marker 本次查询的起点
maxKeys 请求返回的最大数目
isTruncated 指明是否所有查询都返回了;false-本次已经返回所有结果,true-本次还没有返回所有结果
contents 返回的一个Object的容器
+key Object名称
+lastModified 此Object最后一次被修改的时间
+eTag Object的HTTP协议实体标签
+storageClass Object的存储形态
+size Object的内容的大小(字节数)
+owner Object对应Bucket所属用户信息
++id Bucket Owner的用户ID
++displayName Bucket Owner的名称

模拟文件夹功能

在BOS的存储结果中是没有文件夹这个概念的,所有元素都是以Object来存储,但BOS的用户在使用数据时往往需要以文件夹来管理文件。

因此,BOS提供了创建模拟文件夹的能力,其本质上来说是创建了一个size为0的Object。对于这个Object可以上传下载,只是控制台会对以”/“结尾的Object以文件夹的方式展示。

用户可以通过 Delimiter 和 Prefix 参数的配合模拟出文件夹功能。Delimiter 和 Prefix 的组合效果是这样的:

如果把 Prefix 设为某个文件夹名,就可以罗列以此 Prefix 开头的文件,即该文件夹下递归的所有的文件和子文件夹(目录)。文件名在Contents中显示。

如果再把 Delimiter 设置为 “/” 时,返回值就只罗列该文件夹下的文件和子文件夹(目录),该文件夹下的子文件名(目录)返回在 CommonPrefixes 部分,子文件夹下递归的文件和文件夹不被显示。

如下是几个应用方式:

列出Bucket内所有文件

当用户需要获取Bucket下的所有文件时,可以参考分页获取所有Object

递归列出目录下所有文件

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

options = { 
            prefix: 'dir/'
}

is_truncated = true
while is_truncated 
    res = client.list_objects(bucket_name, options)
    is_truncated = res['isTruncated']
    options[:marker] = res['nextMarker'] unless res['nextMarker'].nil?
end

查看目录下的文件和子目录

PrefixDelimiter 结合的情况下,可以列出dir目录下的文件和子目录:

options = { 
            prefix: 'dir/',
            delimiter: '/'
}

is_truncated = true
while is_truncated 
    res = client.list_objects(bucket_name, options)
    is_truncated = res['isTruncated']
    options[:marker] = res['nextMarker'] unless res['nextMarker'].nil?
end

列举Bucket中object的存储属性

当用户完成上传后,如果需要查看指定Bucket中的全部Object的storage class属性,可以通过如下代码实现:

res = client.list_objects(bucket_name)

res['contents'].each { |obj| puts obj['storageClass'] } 

Object权限控制

设置Object的访问权限

如下代码将Object的权限设置为了private:

client.set_object_canned_acl(bucket_name, object_name, Http::BCE_ACL  => 'private')

关于权限的具体内容可以参考《BOS API文档 Object权限控制》。

设置指定用户对Object的访问权限

BOS提供set_object_acl方法和set_object_canned_acl方法来实现指定用户Object的访问权限设置,可以参考如下代码实现:

  1. 通过set_object_canned_aclx-bce-grant-readx-bce-grant-full-control设置指定用户的访问权限

    id_permission = "id=\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",id=\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\""
    client.set_object_canned_acl(bucket_name, object_name, 'x-bce-grant-read' => id_permission)
    
    id_permission = "id=\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",id=\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\""
    client.set_object_canned_acl(bucket_name, object_name, 'x-bce-grant-full-control' => id_permission)
    
  2. 通过set_object_acl设置object访问权限

    acl = [{'grantee' => [{'id' => 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'},
                          {'id' => 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'}],
            'permission' => ['FULL_CONTROL']
    }]
    client.set_object_acl(bucket_name, object_name, acl)
    

注意:

  1. permission中的权限设置包含两个值:READFULL_CONTROL,它们分别对应相关权限。
  2. 设置两个以上(含两个)被授权人时,请参考以上示例的格式,若将数组合并会返回报错。

查看Object的权限

如下代码可以查Object的权限:

client.get_object_acl(bucket_name, object_name)

get_object_acl方法返回的解析类中可供调用的参数有:

参数 说明
accessControlList 标识Object的权限列表
grantee 标识被授权人
-id 被授权人ID
permission 标识被授权人的权限

删除Object的权限

如下代码可以删除Object的权限:

client.delete_object_acl(bucket_name, object_name)

删除文件

删除单个文件

可参考如下代码删除了一个Object:

client.delete_object(bucket_name, object_name)

查看文件是否存在

用户可通过如下操作查看某文件是否存在:

begin
    client.get_object_meta_data(bucket_name, object_name)
rescue BceServerException => e
    puts "#{object_name} not exist!" if e.status_code == 404    
end

获取及更新文件元信息

文件元信息(Object Metadata),是对用户上传BOS的文件的属性描述,分为两种:HTTP标准属性(HTTP Headers)和User Meta(用户自定义元信息)。

获取文件元信息

参考只获取ObjectMetadata

修改文件元信息

BOS修改Object的Metadata通过拷贝Object实现。即拷贝Object的时候,把目的Bucket设置为源Bucket,目的Object设置为源Object,并设置新的Metadata,通过拷贝自身实现修改Metadata的目的。如果不设置新的Metadata,则报错。

user_metadata = { "key1" => "value1" }
options = {
            'user-metadata' => user_metadata
}

client.copy_object(bucket_name, object_name, bucket_name, object_name, options)
puts client.get_object_meta_data(bucket_name, object_name)['user-metadata']['key1']

拷贝Object

拷贝一个文件

用户可以通过copyObject方法拷贝一个Object,如下代码所示:

client.copy_object(source_bucket_name, source_object_key, target_bucket_name, target_object_key)

copy_object方法可以通过options配置可选参数,参数列表参考如下:

参数 说明
user-metadata 用户自定义Meta,包含Key-Value对
eTag Source Object的eTag,若选择上传,则会对Target Object和Source Object的eTag进行比对,若不相同,则返回错误。

同步Copy

当前BOS的CopyObject接口是通过同步方式实现的。同步方式下,BOS端会等待Copy实际完成才返回成功。同步Copy能帮助用户更准确的判断Copy状态,但用户感知的复制时间会变长,且复制时间和文件大小成正比。

同步Copy方式更符合业界常规,提升了与其它平台的兼容性。同步Copy方式还简化了BOS服务端的业务逻辑,提高了服务效率。

分块拷贝

除了通过CopyObject接⼝拷贝文件以外,BOS还提供了另外一种拷贝模式——Multipart Upload Copy。用户可以在如下的应用场景内(但不仅限于此),使用Multipart Upload Copy,如:

  • 需要支持断点拷贝。
  • 拷贝超过5GB大小的文件。
  • 网络条件较差,和BOS的服务器之间的连接经常断开。

下面将介绍分步实现三步拷贝。

三步拷贝包含init、“拷贝分块”和complete三步,其中init和complete的操作同分块上传一致,可直接参考[初始化Multipart Upload](#初始化Multipart Upload)和完成分块上传

left_size = client.get_object_meta_data(source_bucket_name, source_object_key)['content-length']
offset = 0
part_number = 1
part_list = []

while left_size > 0 do
    part_size = 5 * 1024 * 1024
    if left_size < part_size
        part_size = left_size
    end

    response = client.upload_part_copy(
        source_bucket_name, source_object_key, target_bucket_name, target_object_key, upload_id, part_number, part_size, offset)
    left_size -= part_size
    offset += part_size
    # your should store every part number and etag to invoke complete multi-upload
    part_list << {
        "partNumber" => part_number,
        "eTag" => response["eTag"]
    }
    part_number += 1
end

注意: size参数以字节为单位,定义每个分块的大小,除最后一个Part以外,其他的Part大小都要大于5MB。

异常处理

BOS异常提示有如下四种方式:

异常方法 说明
BceHttpException 客户端异常
BceServerException 服务器异常
BceHttpException net::http相关异常

用户可以使用rescue获取某个事件所产生的异常:

begin
    client.get_object_meta_data(bucket_name, object_name)
rescue Exception => e
    puts "Catch a http exception" if e.is_a?(BceHttpException)
    puts "Catch a client exception" if e.is_a?(BceClientException)
    puts "Catch a server exception" if e.is_a?(BceServerException)
end

客户端异常

客户端异常表示客户端尝试向BOS发送请求以及数据传输时遇到的异常。

服务端异常

当BOS服务端出现异常时,BOS服务端会返回给用户相应的错误信息,以便定位问题。常见服务端异常可参见BOS错误信息格式

SDK日志

BOS Ruby SDK支持四个级别的日志(默认为Logger::INFO级别),支持设置输出日志文件的目录,详细可以参考Log模块。示例代码:

# 默认日志路径:DEFAULT_LOG_FILE = "./baidubce-sdk.log"
Log.set_log_file(file_path)

# 四个日志级别:Logger::DEBUG | Logger::INFO | Logger::ERROR | Logger::FATAL
Log.set_log_level(Logger::DEBUG)

版本变更记录

  • Ruby SDK开发包[2018-05-21] 版本号 0.9.0
    • 创建、查看、罗列、删除Bucket,获取位置和判断是否存在
    • 支持管理Bucket的生命周期、日志、ACL、存储类型
    • 上传、下载、删除、罗列Object,支持追加上传、分块上传、分块拷贝

Releases

No releases published

Packages

No packages published