No commit activity in last 3 years
No release in over 3 years
A Ruby program to facilitate accessing Aliyun Object Storage Service
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.10
~> 5.8
~> 10.4
~> 3.3
~> 0.10.0
~> 1.22

Runtime

 Project Readme

Aliyun OSS SDK for Ruby

Gem Version Build Status Coverage Status


Aliyun OSS SDK for Ruby是用于方便访问阿里云OSS(Object Storage Service) RESTful API的Ruby客户端程序。了解OSS的的更多信息请访问OSS官网: http://www.aliyun.com/product/oss

运行环境

  • Ruby版本 >= 1.9.3
  • 支持Ruby运行环境的Windows/Linux/OS X

安装Ruby请参考:https://www.ruby-lang.org/zh_cn/downloads/

快速开始

开通OSS账号

登录官网:http://www.aliyun.com/product/oss ,点击“立即开通”。按照提示 开通OSS服务。开通服务之后请在“管理控制台”中查看您的AccessKeyId和 AccessKeySecret,在使用Aliyun OSS SDK时需要提供您的这两个信息。

安装Aliyun OSS SDK for Ruby

gem install aliyun-sdk

并在你的程序中或者irb命令下包含:

require 'aliyun_sdk/oss'

注意:

  1. SDK依赖的一些gem是本地扩展的形式,因此安装完Ruby之后还需要安装 ruby-dev以支持编译本地扩展的gem
  2. SDK依赖的处理XML的gem(nokogiri)要求环境中包含zlib库

以Ubuntu为例,安装上述依赖的方法:

sudo apt-get install ruby-dev
sudo apt-get install zlib1g-dev

其他系统类似。

创建Client

client = AliyunSDK::OSS::Client.new(
  :endpoint => 'endpoint',
  :access_key_id => 'access_key_id',
  :access_key_secret => 'access_key_secret')

其中endpoint是OSS服务的地址,根据节点区域不同,这个地址可能不一样,例如 杭州节点的地址是:http://oss-cn-hangzhou.aliyuncs.com,其他节点的地址见: 节点列表

access_key_idaccess_key_secret是您的服务凭证,在官网的“管理控制 台”上面可以查看。请妥善保管您的AccessKeySecret,泄露之后可能影响您的 数据安全

使用用户绑定的域名作为endpoint

OSS支持自定义域名绑定,允许用户将自己的域名指向阿里云OSS的服务地址 (CNAME),这样用户迁移到OSS上时应用内资源的路径可以不用修改。绑定的域 名指向OSS的一个bucket。绑定域名的操作只能在OSS控制台进行。更多关于自定 义域名绑定的内容请到官网了解:OSS自定义域名绑定

用户绑定了域名后,使用SDK时指定的endpoint可以使用标准的OSS服务地址,也 可以使用用户绑定的域名:

client = AliyunSDK::OSS::Client.new(
  :endpoint => 'http://img.my-domain.com',
  :access_key_id => 'access_key_id',
  :access_key_secret => 'access_key_secret',
  :cname => true)

有以下几点需要注意:

  1. 在Client初始化时必须指定:cname为true
  2. 自定义域名绑定了OSS的一个bucket,所以用这种方式创建的client不能进行 list_buckets操作
  3. 在{AliyunSDK::OSS::Client#get_bucket}时仍需要指定bucket名字,并且要与 域名所绑定的bucket名字相同

使用STS创建Client

OSS支持用户使用STS进行访问,更多有关STS的内容,请参考 阿里云STS。 在使用STS之前需要先向STS申请一个临时token, aliyun-sdk中包含了STS的SDK,使用时只需要require 'aliyun/sts'即可:

require 'aliyun/sts'
sts = AliyunSDK::STS::Client.new(
  access_key_id: 'access_key_id',
  access_key_secret: 'access_key_secret')

token = sts.assume_role('role-arn', 'my-app')

client = AliyunSDK::OSS::Client.new(
  :endpoint => 'http://oss-cn-hangzhou.aliyuncs.com',
  :access_key_id => token.access_key_id,
  :access_key_secret => token.access_key_secret,
  :sts_token => token.security_token)

注意使用STS时必须指定:sts_token参数。用户还可以通过STS::Client申请 带Policy的token,细节请参考API文档

列出当前所有的Bucket

buckets = client.list_buckets
buckets.each{ |b| puts b.name }

list_buckets返回的是一个迭代器,用户依次获取每个Bucket的信息。Bucket 对象的结构请查看API文档中的{AliyunSDK::OSS::Bucket}

创建一个Bucket

bucket = client.create_bucket('my-bucket')

列出Bucket中所有的Object

bucket = client.get_bucket('my-bucket')
objects = bucket.list_objects
objects.each{ |o| puts o.key }

list_objects返回的是一个迭代器,用户依次获取每个Object的信息。Object 对象的结构请查看API文档中的{AliyunSDK::OSS::Object}

在Bucket中创建一个Object

bucket.put_object(object_key){ |stream| stream << 'hello world' }

用户也可以通过上传本地文件创建一个Object:

bucket.put_object(object_key, :file => local_file)

从Bucket中下载一个Object

bucket.get_object(object_key){ |content| puts content }

用户也可以将Object下载到本地文件中:

bucket.get_object(object_key, :file => local_file)

拷贝Object

bucket.copy_object(from_key, to_key)

判断一个Object是否存在

bucket.object_exists?(object_key)

更多Bucket的操作请参考API文档中的{AliyunSDK::OSS::Bucket}

模拟目录结构

OSS是Object存储服务,本身不支持目录结构,所有的object都是“平”的。但是 用户可以通过设置object的key为"foo/bar/file"这样的形式来模拟目录结构。 假设现在有以下Objects:

foo/x
foo/bar/f1
foo/bar/dir/file
foo/hello/file

列出"foo/"目录下的所有文件就是以"foo/"为prefix进行list_objects,但 是这样也会把"foo/bar/"下的所有object也列出来。为此需要用到delimiter参 数,其含义是从prefix往后遇到第一个delimiter时停止,这中间的key作为 Object的common prefix,包含在list_objects的结果中。

objs = bucket.list_objects(:prefix => 'foo/', :delimiter => '/')
objs.each do |i|
  if i.is_a?(AliyunSDK::OSS::Object) # a object
    puts "object: #{i.key}"
  else
    puts "common prefix: #{i}"
  end
end
# output
object: foo/x
common prefix: foo/bar/
common prefix: foo/hello/

Common prefix让用户不需要遍历所有的object(可能数量巨大)而找出前缀, 在模拟目录结构时非常有用。

上传回调

put_objectresumable_upload时可以指定一个Callback,这样在文件 成功上传到OSS之后,OSS会向用户提供的服务器地址发起一个HTTP POST请求, 以通知用户相应的事件发生了。用户可以在收到这个通知之后进行相应的动作, 例如更新数据库、统计行为等。更多有关上传回调的内容请参考OSS上传回调

下面的例子将演示如何使用上传回调:

callback = AliyunSDK::OSS::Callback.new(
  url: 'http://10.101.168.94:1234/callback',
  query: {user: 'put_object'},
  body: 'bucket=${bucket}&object=${object}'
)

begin
  bucket.put_object('files/hello', callback: callback)
rescue AliyunSDK::OSS::CallbackError => e
  puts "Callback failed: #{e.message}"
end

注意

  1. callback的url不能包含query string,而应该在:query参数中指定
  2. 可能出现文件上传成功,但是执行回调失败的情况,此时client会抛出 CallbackError,用户如果要忽略此错误,需要显式接住这个异常。
  3. 详细的例子可以参考callback.rb
  4. 接受回调的server可以参考callback_server.rb

断点上传/下载

OSS支持大文件的存储,用户如果上传/下载大文件(Object)的时候中断了(网络 闪断、程序崩溃、机器断电等),重新上传/下载是件很费资源的事情。OSS支持 Multipart的功能,可以在上传/下载时将大文件进行分片传输。Aliyun OSS SDK 基于此提供了断点上传/下载的功能。如果发生中断,可以从上次中断的地方继 续进行上传/下载。对于文件大小超过100MB的文件,都建议采用断点上传/下载 的方式进行。

断点上传

bucket.resumable_upload(object_key, local_file, :cpt_file => cpt_file)

其中:cpt_file指定保存上传中间状态的checkpoint文件所在的位置,如果用户 没有指定,SDK将为用户在local_file所在的目录生成一个 local_file.cpt。上传中断后,只需要提供相同的cpt文件,上传将会从 中断的点继续上传。所以典型的上传代码是:

retry_times = 5
retry_times.times do
  begin
    bucket.resumable_upload(object_key, local_file)
  rescue => e
    logger.error(e.message)
  end
end

注意:

  1. SDK会将上传的中间状态信息记录在cpt文件中,所以要确保用户对cpt文 件有写权限
  2. cpt文件记录了上传的中间状态信息并自带了校验,用户不能去编辑它,如 果cpt文件损坏则上传无法继续。整个上传完成后cpt文件会被删除。

断点下载

bucket.resumable_download(object_key, local_file, :cpt_file => cpt_file)

其中:cpt_file指定保存下载中间状态的checkpoint文件所在的位置,如果用户 没有指定,SDK将为用户在local_file所在的目录生成一个 local_file.cpt。下载中断后,只需要提供相同的cpt文件,下载将会从 中断的点继续下载。所以典型的下载代码是:

retry_times = 5
retry_times.times do
  begin
    bucket.resumable_download(object_key, local_file)
  rescue => e
    logger.error(e.message)
  end
end

注意:

  1. 在下载过程中,对于下载完成的每个分片,会在local_file所在的目录生 成一个local_file.part.N的临时文件。整个下载完成后这些文件会被删除。 用户不能去编辑或删除part文件,否则下载不能继续。
  2. SDK会将下载的中间状态信息记录在cpt文件中,所以要确保用户对cpt文 件有写权限
  3. cpt文件记录了下载的中间状态信息并自带了校验,用户不能去编辑它,如 果cpt文件损坏则下载无法继续。整个下载完成后cpt文件会被删除。

可追加的文件

阿里云OSS中的Object分为两种类型:Normal和Appendable。

  • 对于Normal Object,每次上传都是作为一个整体,如果一个Object已存在, 两次上传相同key的Object将会覆盖原有的Object
  • 对于Appendable Object,第一次通过append_object创建它,后续的 append_object不会覆盖原有的内容,而是在Object末尾追加内容
  • 不能向Normal Object追加内容
  • 不能拷贝一个Appendable Object

创建一个Appendable Object

bucket.append_object(object_key, 0){ |stream| stream << "hello world" }

第二个参数是追加的位置,对一个Object第一次追加时,这个参数为0。后续的 追加这个参数要求是追加前Object的长度。

当然,也可以从文件中读取追加的内容:

bucket.append_object(object_key, 0, :file => local_file)

向Object追加内容

pos = bucket.get_object(object_key).size
next_pos = bucket.append_object(object_key, pos, :file => local_file)

程序第一次追加时,可以通过{AliyunSDK::OSS::Bucket#get_object}获取文件的长度, 后续追加时,可以根据{AliyunSDK::OSS::Bucket#append_object}返回的下次追加长度。

注意:如果并发地append_objectnext_pos并不总是对的。

Object meta信息

在上传Object时,除了Object内容,OSS还允许用户为Object设置一些"meta信息 ",这些meta信息是一个个的Key-Value对,用于标识Object特有的属性信息。这 些meta信息会跟Object一起存储,并在get_objectget_object时返 回给用户。

bucket.put_object(object_key, :file => local_file,
                  :metas => {
                    'key1' => 'value1',
                    'key2' => 'value2'})

obj = bucket.get_object(object_key, :file => localfile)
puts obj.metas

关于meta信息有以下几点需要注意:

  1. meta信息的key和value都只能是简单的ASCII非换行字符,并且总的大小不能超过8KB。
  2. Copy object时默认将拷贝源object的meta信息,如果用户不希望这么做,需要 显式地将:meta_directive设置成{AliyunSDK::OSS::MetaDirective::REPLACE}

权限控制

OSS允许用户对Bucket和Object分别设置访问权限,方便用户控制自己的资源可 以被如何访问。对于Bucket,有三种访问权限:

  • public-read-write 允许匿名用户向该Bucket中创建/获取/删除Object
  • public-read 允许匿名用户获取该Bucket中的Object
  • private 不允许匿名访问,所有的访问都要经过签名

创建Bucket时,默认是private权限。之后用户可以通过bucket.acl=来设置 Bucket的权限。

bucket.acl = AliyunSDK::OSS::ACL::PUBLIC_READ
puts bucket.acl # public-read

对于Object,有四种访问权限:

  • default 继承所属的Bucket的访问权限,即与所属Bucket的权限值一样
  • public-read-write 允许匿名用户读写该Object
  • public-read 允许匿名用户读该Object
  • private 不允许匿名访问,所有的访问都要经过签名

创建Object时,默认为default权限。之后用户可以通过 bucket.set_object_acl来设置Object的权限。

acl = bucket.get_object_acl(object_key)
puts acl # default
bucket.set_object_acl(object_key, AliyunSDK::OSS::ACL::PUBLIC_READ)
acl = bucket.get_object_acl(object_key)
puts acl # public-read

需要注意的是:

  1. 如果设置了Object的权限,则访问该Object时进行权限认证时会优先判断 Object的权限,而Bucket的权限设置会被忽略。

  2. 允许匿名访问时(设置了public-read或者public-read-write权限),用户 可以直接通过浏览器访问,例如:

     http://bucket-name.oss-cn-hangzhou.aliyuncs.com/object.jpg
    
  3. 访问具有public权限的Bucket/Object时,也可以通过创建匿名的Client来进行:

     # 不填access_key_id和access_key_secret,将创建匿名Client,只能访问
     # 具有public权限的Bucket/Object
     client = Client.new(:endpoint => 'oss-cn-hangzhou.aliyuncs.com')
     bucket = client.get_bucket('public-bucket')
     obj = bucket.get_object('public-object', :file => local_file)
    

运行examples

SDK的examples/目录下有一些展示SDK功能的示例程序,用户稍加配置就可以直 接运行。examples需要的权限信息和bucket信息从用户HOME目录下的配置文件 ~/.oss.yml中读取,其中应该包含以下字段(注意冒号后面需要有一个空格):

endpoint: oss-cn-hangzhou.aliyuncs.com
cname: false
access_key_id: <ACCESS KEY ID>
access_key_secret: <ACCESS KEY SECRET>
bucket: <BUCKET NAME>

用户需要创建(如果不存在)或者修改其中的内容,然后运行:

ruby examples/aliyun/oss/bucket.rb

运行测试

bundle exec rake spec

export RUBY_SDK_OSS_ENDPOINT=endpoint
export RUBY_SDK_OSS_ID=AccessKeyId
export RUBY_SDK_OSS_KEY=AccessKeySecret
export RUBY_SDK_OSS_BUCKET=bucket-name

bundle exec rake test

更多

更多文档请查看: