OSS Ruby SDK提供一系列的接口方便用户管理某个存储空间(Bucket)下的多个文件(Object)。

列举所有文件

通过bucket.list_objects接口来列举指定Bucket下的所有文件,包括以下主要参数:

  • :prefix指定只列出符合特定前缀的文件。
  • :marker指定只列出文件名大于marker之后的文件。
  • :delimiter用于获取文件的公共前缀。

以下代码用于列举指定Bucket下符合条件的文件:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

bucket = client.get_bucket('my-bucket')
# 列出所有文件
objects = bucket.list_objects
objects.each { |o| puts o.key }

# 列出前缀为'my-'的所有文件
objects = bucket.list_objects(:prefix => 'my-')
objects.each { |o| puts o.key }

# 列出前缀为'my-'且在'my-object'之后的所有文件
objects = bucket.list_objects(:prefix => 'my-', :marker => 'my-object')
objects.each { |o| puts o.key }

模拟目录结构

OSS是基于对象的存储服务,没有目录的概念。存储在某个Bucket中的所有文件都是通过文件的key来唯一标识,并没有层级的结构。通过OSS提供的公共前缀的功能,您可以方便地模拟目录结构,将文件分门别类地存放在不同的目录下。公共前缀的概念请参考查看对象列表

假设某个Bucket中有如下文件:

foo/x
foo/y
foo/bar/a
foo/bar/b
foo/hello/C/1
foo/hello/C/2
...
foo/hello/C/9999

然后通过调用list_dir函数来列举指定目录下的文件和子目录:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

def list_dir(dir)
  objects = bucket.list_objects(:prefix => dir, :delimiter => '/')
  objects.each do |obj|
    if obj.is_a?(OSS::Object) # object
      puts "Object: #{obj.key}"
    else # common prefix
      puts "SubDir: #{obj}"
    end
  end
end

运行结果如下:

> list_dir('foo/')
=> SubDir: foo/bar/
   SubDir: foo/hello/
   Object: foo/x
   Object: foo/y

> list_dir('foo/bar/')
=> Object: foo/bar/a
   Object: foo/bar/b

> list_dir('foo/hello/C/')
=> Object: foo/hello/C/1
   Object: foo/hello/C/2
   ...
   Object: foo/hello/C/9999

文件元信息

向OSS上传文件时,除了文件内容,还可以指定文件的一些属性信息,这些属性信息称为元信息。 元信息在上传时与文件一起存储,在下载时与文件一起返回。

在Ruby SDK中,文件元信息用 Hash来表示,其他key和value均为 String类型。文件元信息会附在HTTP Headers中, 而HTTP协议规定请求头部不能包含复杂字符,所以元信息只能是简单的ASCII可见字符且不能包含换行。
说明 所有元信息的总大小不能超过8KB。

使用bucket.put_objectbucket.append_objectbucket.resumable_upload时都可以通过指定:metas参数来指定文件的元信息。

以下代码用于指定文件元信息:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

bucket.put_object(
  'my-object-1',
  :file => 'local-file',
  :metas => {'year' => '2016', 'people' => 'mary'})

bucket.append_object(
  'my-object-2', 0,
  :file => 'local-file',
  :metas => {'year' => '2016', 'people' => 'mary'})

bucket.resumable_upload(
  'my-object',
  'local-file',
  :metas => {'year' => '2016', 'people' => 'mary'})

通过bucket.update_object_metas命令来更新文件元信息:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

bucket.update_object_metas('my-object', {'year' => '2017'})

拷贝文件

使用bucket.copy_object拷贝一个文件,并通过:meta_directive参数指定文件元信息。拷贝时对文件元信息的处理有两种选择:

  • 如果没有指定meta参数,则与源文件相同,即拷贝源文件的元信息。
  • 如果指定了meta参数,则使用新的元信息覆盖源文件的信息。

以下代码用于拷贝文件:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

# 拷贝文件元信息。
bucket.copy_object(
  'my-object', 'copy-object',
  :meta_directive => Aliyun::OSS::MetaDirective::COPY)

# 覆盖文件元信息。
bucket.copy_object(
  'my-object', 'copy-object',
  :metas => {'year' => '2017'},
  :meta_directive => Aliyun::OSS::MetaDirective::REPLACE)

删除文件

通过bucket.delete_object来删除某个文件:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

bucket.delete_object('my-object')

批量删除文件

通过bucket.batch_delete_objects批量删除文件,并通过:quiet参数来指定是否返回删除的结果:

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

objs = ['my-object-1', 'my-object-2']
result = bucket.batch_delete_objects(objs)
# 默认返回删除成功的文件。
puts result #['my-object-1', 'my-object-2']

objs = ['my-object-3', 'my-object-4']
result = bucket.batch_delete_objects(objs, :quiet => true)
# 不返回删除的结果。
puts result #[]

设置文件访问权限

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

  • default:继承所属的Bucket的访问权限,即与所属Bucket的访问权限一样。
  • public-read-write:允许匿名用户读写该Object。
  • public-read:允许匿名用户读该Object。
  • private:不允许匿名访问,所有的访问都要经过签名。
创建Object时,默认为default权限。之后您可以通过 bucket.set_object_acl来设置Object的权限。
require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  endpoint: 'endpoint',
  access_key_id: 'AccessKeyId', access_key_secret: 'AccessKeySecret')

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

acl = bucket.get_object_acl('my-object')
puts acl # default
bucket.set_object_acl('my-object', Aliyun::OSS::ACL::PUBLIC_READ)
acl = bucket.get_object_acl('my-object')
puts acl # public-read
  • 如果没有设置Object的权限,即Object的ACL为继承Bucket,此时Object的权限和Bucket权限一致。
  • 如果Object的权限为继承Bucket以外的三种权限时,访问该Object进行权限认证时会优先判断Object的权限,此时Bucket的权限设置会被忽略。
  • 允许匿名访问时(设置了public-read或者public-read-write权限),您可以直接通过浏览器访问,例如http://bucket-name.oss-cn-hangzhou.aliyuncs.com/object.jpg
  • 您也可以通过创建匿名的Client来访问具有public-read或者public-read-write权限的Object。
    require 'aliyun/oss'
    
        # 不填access_key_id和access_key_secret,将创建匿名Client,只能访问具有public权限的Object。
        client = Aliyun::OSS::Client.new(endpoint: 'endpoint')    
    
        bucket.get_object('my-object', :file => 'local_file')