aliyun-oss-ruby-sdk 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +95 -0
  3. data/README.md +423 -0
  4. data/examples/aliyun/oss/bucket.rb +144 -0
  5. data/examples/aliyun/oss/callback.rb +61 -0
  6. data/examples/aliyun/oss/object.rb +182 -0
  7. data/examples/aliyun/oss/resumable_download.rb +42 -0
  8. data/examples/aliyun/oss/resumable_upload.rb +49 -0
  9. data/examples/aliyun/oss/streaming.rb +124 -0
  10. data/examples/aliyun/oss/using_sts.rb +48 -0
  11. data/examples/aliyun/sts/assume_role.rb +59 -0
  12. data/lib/aliyun_sdk/common.rb +6 -0
  13. data/lib/aliyun_sdk/common/exception.rb +18 -0
  14. data/lib/aliyun_sdk/common/logging.rb +46 -0
  15. data/lib/aliyun_sdk/common/struct.rb +56 -0
  16. data/lib/aliyun_sdk/oss.rb +16 -0
  17. data/lib/aliyun_sdk/oss/bucket.rb +661 -0
  18. data/lib/aliyun_sdk/oss/client.rb +106 -0
  19. data/lib/aliyun_sdk/oss/config.rb +39 -0
  20. data/lib/aliyun_sdk/oss/download.rb +255 -0
  21. data/lib/aliyun_sdk/oss/exception.rb +108 -0
  22. data/lib/aliyun_sdk/oss/http.rb +338 -0
  23. data/lib/aliyun_sdk/oss/iterator.rb +92 -0
  24. data/lib/aliyun_sdk/oss/multipart.rb +74 -0
  25. data/lib/aliyun_sdk/oss/object.rb +15 -0
  26. data/lib/aliyun_sdk/oss/protocol.rb +1499 -0
  27. data/lib/aliyun_sdk/oss/struct.rb +208 -0
  28. data/lib/aliyun_sdk/oss/upload.rb +238 -0
  29. data/lib/aliyun_sdk/oss/util.rb +89 -0
  30. data/lib/aliyun_sdk/sts.rb +9 -0
  31. data/lib/aliyun_sdk/sts/client.rb +38 -0
  32. data/lib/aliyun_sdk/sts/config.rb +22 -0
  33. data/lib/aliyun_sdk/sts/exception.rb +53 -0
  34. data/lib/aliyun_sdk/sts/protocol.rb +130 -0
  35. data/lib/aliyun_sdk/sts/struct.rb +64 -0
  36. data/lib/aliyun_sdk/sts/util.rb +48 -0
  37. data/lib/aliyun_sdk/version.rb +7 -0
  38. data/spec/aliyun/oss/bucket_spec.rb +597 -0
  39. data/spec/aliyun/oss/client/bucket_spec.rb +554 -0
  40. data/spec/aliyun/oss/client/client_spec.rb +297 -0
  41. data/spec/aliyun/oss/client/resumable_download_spec.rb +220 -0
  42. data/spec/aliyun/oss/client/resumable_upload_spec.rb +413 -0
  43. data/spec/aliyun/oss/http_spec.rb +83 -0
  44. data/spec/aliyun/oss/multipart_spec.rb +686 -0
  45. data/spec/aliyun/oss/object_spec.rb +785 -0
  46. data/spec/aliyun/oss/service_spec.rb +142 -0
  47. data/spec/aliyun/oss/util_spec.rb +50 -0
  48. data/spec/aliyun/sts/client_spec.rb +150 -0
  49. data/spec/aliyun/sts/util_spec.rb +39 -0
  50. data/tests/config.rb +31 -0
  51. data/tests/test_content_encoding.rb +54 -0
  52. data/tests/test_content_type.rb +95 -0
  53. data/tests/test_custom_headers.rb +70 -0
  54. data/tests/test_encoding.rb +77 -0
  55. data/tests/test_large_file.rb +66 -0
  56. data/tests/test_multipart.rb +97 -0
  57. data/tests/test_object_acl.rb +49 -0
  58. data/tests/test_object_key.rb +68 -0
  59. data/tests/test_object_url.rb +69 -0
  60. data/tests/test_resumable.rb +40 -0
  61. metadata +240 -0
@@ -0,0 +1,144 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__))
4
+ require 'yaml'
5
+ require 'aliyun/oss'
6
+
7
+ # 初始化OSS client
8
+ AliyunSDK::Common::Logging.set_log_level(Logger::DEBUG)
9
+ conf_file = '~/.oss.yml'
10
+ conf = YAML.load(File.read(File.expand_path(conf_file)))
11
+ client = AliyunSDK::OSS::Client.new(
12
+ :endpoint => conf['endpoint'],
13
+ :cname => conf['cname'],
14
+ :access_key_id => conf['access_key_id'],
15
+ :access_key_secret => conf['access_key_secret'])
16
+ bucket = client.get_bucket(conf['bucket'])
17
+
18
+ # 辅助打印函数
19
+ def demo(msg)
20
+ puts "######### #{msg} ########"
21
+ puts
22
+ yield
23
+ puts "-------------------------"
24
+ puts
25
+ end
26
+
27
+ # 列出当前所有的bucket
28
+ demo "List all buckets" do
29
+ buckets = client.list_buckets
30
+ buckets.each{ |b| puts "Bucket: #{b.name}"}
31
+ end
32
+
33
+ # 创建bucket,如果同名的bucket已经存在,则创建会失败
34
+ demo "Create bucket" do
35
+ begin
36
+ bucket_name = 't-foo-bar'
37
+ client.create_bucket(bucket_name, :location => 'oss-cn-hangzhou')
38
+ puts "Create bucket success: #{bucket_name}"
39
+ rescue => e
40
+ puts "Create bucket failed: #{bucket_name}, #{e.message}"
41
+ end
42
+ end
43
+
44
+ # 向bucket中添加5个空的object:
45
+ # foo/obj1, foo/bar/obj1, foo/bar/obj2, foo/xxx/obj1
46
+
47
+ demo "Put objects before list" do
48
+ bucket.put_object('foo/obj1')
49
+ bucket.put_object('foo/bar/obj1')
50
+ bucket.put_object('foo/bar/obj2')
51
+ bucket.put_object('foo/xxx/obj1')
52
+ bucket.put_object('中国の')
53
+ end
54
+
55
+ # list bucket下所有objects
56
+ demo "List first 10 objects" do
57
+ objects = bucket.list_objects
58
+
59
+ objects.take(10).each do |o|
60
+ puts "Object: #{o.key}, type: #{o.type}, size: #{o.size}"
61
+ end
62
+ end
63
+
64
+ # list bucket下所有前缀为foo/bar/的object
65
+ demo "List first 10 objects with prefix 'foo/bar/'" do
66
+ objects = bucket.list_objects(:prefix => 'foo/bar/')
67
+
68
+ objects.take(10).each do |o|
69
+ puts "Object: #{o.key}, type: #{o.type}, size: #{o.size}"
70
+ end
71
+ end
72
+
73
+ # 获取object的common prefix,common prefix是指bucket下所有object(也可
74
+ # 以指定特定的前缀)的公共前缀,这在object数量巨多的时候很有用,例如有
75
+ # 如下的object:
76
+ # /foo/bar/obj1
77
+ # /foo/bar/obj2
78
+ # ...
79
+ # /foo/bar/obj9999999
80
+ # /foo/xx/
81
+ # 指定foo/为prefix,/为delimiter,则返回的common prefix为
82
+ # /foo/bar/, /foo/xxx/
83
+ # 这可以表示/foo/目录下的子目录。如果没有common prefix,你可能要遍历所
84
+ # 有的object来找公共的前缀
85
+
86
+ demo "List first 10 objects/common prefixes" do
87
+ objects = bucket.list_objects(:prefix => 'foo/', :delimiter => '/')
88
+
89
+ objects.take(10).each do |o|
90
+ if o.is_a?(AliyunSDK::OSS::Object)
91
+ puts "Object: #{o.key}, type: #{o.type}, size: #{o.size}"
92
+ else
93
+ puts "Common prefix: #{o}"
94
+ end
95
+ end
96
+ end
97
+
98
+ # 获取/设置Bucket属性: ACL, Logging, Referer, Website, LifeCycle, CORS
99
+ demo "Get/Set bucket properties: ACL/Logging/Referer/Website/Lifecycle/CORS" do
100
+ puts "Bucket acl before: #{bucket.acl}"
101
+ bucket.acl = AliyunSDK::OSS::ACL::PUBLIC_READ
102
+ puts "Bucket acl now: #{bucket.acl}"
103
+ puts
104
+
105
+ puts "Bucket logging before: #{bucket.logging.to_s}"
106
+ bucket.logging = AliyunSDK::OSS::BucketLogging.new(
107
+ :enable => true, :target_bucket => conf['bucket'], :target_prefix => 'foo/')
108
+ puts "Bucket logging now: #{bucket.logging.to_s}"
109
+ puts
110
+
111
+ puts "Bucket referer before: #{bucket.referer.to_s}"
112
+ bucket.referer = AliyunSDK::OSS::BucketReferer.new(
113
+ :allow_empty => true, :whitelist => ['baidu.com', 'aliyun.com'])
114
+ puts "Bucket referer now: #{bucket.referer.to_s}"
115
+ puts
116
+
117
+ puts "Bucket website before: #{bucket.website.to_s}"
118
+ bucket.website = AliyunSDK::OSS::BucketWebsite.new(
119
+ :enable => true, :index => 'default.html', :error => 'error.html')
120
+ puts "Bucket website now: #{bucket.website.to_s}"
121
+ puts
122
+
123
+ puts "Bucket lifecycle before: #{bucket.lifecycle.map(&:to_s)}"
124
+ bucket.lifecycle = [
125
+ AliyunSDK::OSS::LifeCycleRule.new(
126
+ :id => 'rule1', :enable => true, :prefix => 'foo/', :expiry => 1),
127
+ AliyunSDK::OSS::LifeCycleRule.new(
128
+ :id => 'rule2', :enable => false, :prefix => 'bar/', :expiry => Date.new(2016, 1, 1))
129
+ ]
130
+ puts "Bucket lifecycle now: #{bucket.lifecycle.map(&:to_s)}"
131
+ puts
132
+
133
+ puts "Bucket cors before: #{bucket.cors.map(&:to_s)}"
134
+ bucket.cors = [
135
+ AliyunSDK::OSS::CORSRule.new(
136
+ :allowed_origins => ['aliyun.com', 'http://www.taobao.com'],
137
+ :allowed_methods => ['PUT', 'POST', 'GET'],
138
+ :allowed_headers => ['Authorization'],
139
+ :expose_headers => ['x-oss-test'],
140
+ :max_age_seconds => 100)
141
+ ]
142
+ puts "Bucket cors now: #{bucket.cors.map(&:to_s)}"
143
+ puts
144
+ end
@@ -0,0 +1,61 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__))
4
+ require 'yaml'
5
+ require 'json'
6
+ require 'aliyun/oss'
7
+
8
+ ##
9
+ # 用户在上传文件时可以指定“上传回调”,这样在文件上传成功后OSS会向用户
10
+ # 提供的服务器地址发起一个HTTP POST请求,相当于一个通知机制。用户可以
11
+ # 在收到回调的时候做相应的动作。
12
+ # 1. 如何接受OSS的回调可以参考代码目录下的
13
+ # rails/aliyun_oss_callback_server.rb
14
+ # 2. 只有put_object和resumable_upload支持上传回调
15
+
16
+ # 初始化OSS client
17
+ AliyunSDK::Common::Logging.set_log_level(Logger::DEBUG)
18
+ conf_file = '~/.oss.yml'
19
+ conf = YAML.load(File.read(File.expand_path(conf_file)))
20
+ bucket = AliyunSDK::OSS::Client.new(
21
+ :endpoint => conf['endpoint'],
22
+ :cname => conf['cname'],
23
+ :access_key_id => conf['access_key_id'],
24
+ :access_key_secret => conf['access_key_secret']).get_bucket(conf['bucket'])
25
+
26
+ # 辅助打印函数
27
+ def demo(msg)
28
+ puts "######### #{msg} ########"
29
+ puts
30
+ yield
31
+ puts "-------------------------"
32
+ puts
33
+ end
34
+
35
+ demo "put object with callback" do
36
+ callback = AliyunSDK::OSS::Callback.new(
37
+ url: 'http://10.101.168.94:1234/callback',
38
+ query: {user: 'put_object'},
39
+ body: 'bucket=${bucket}&object=${object}'
40
+ )
41
+
42
+ begin
43
+ bucket.put_object('files/hello', callback: callback)
44
+ rescue AliyunSDK::OSS::CallbackError => e
45
+ puts "Callback failed: #{e.message}"
46
+ end
47
+ end
48
+
49
+ demo "resumable upload with callback" do
50
+ callback = AliyunSDK::OSS::Callback.new(
51
+ url: 'http://10.101.168.94:1234/callback',
52
+ query: {user: 'resumable_upload'},
53
+ body: 'bucket=${bucket}&object=${object}'
54
+ )
55
+
56
+ begin
57
+ bucket.resumable_upload('files/world', '/tmp/x', callback: callback)
58
+ rescue AliyunSDK::OSS::CallbackError => e
59
+ puts "Callback failed: #{e.message}"
60
+ end
61
+ end
@@ -0,0 +1,182 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__))
4
+ require 'yaml'
5
+ require 'aliyun/oss'
6
+
7
+ # 初始化OSS client
8
+ AliyunSDK::Common::Logging.set_log_level(Logger::DEBUG)
9
+ conf_file = '~/.oss.yml'
10
+ conf = YAML.load(File.read(File.expand_path(conf_file)))
11
+ bucket = AliyunSDK::OSS::Client.new(
12
+ :endpoint => conf['endpoint'],
13
+ :cname => conf['cname'],
14
+ :access_key_id => conf['access_key_id'],
15
+ :access_key_secret => conf['access_key_secret']).get_bucket(conf['bucket'])
16
+
17
+ # 辅助打印函数
18
+ def demo(msg)
19
+ puts "######### #{msg} ########"
20
+ puts
21
+ yield
22
+ puts "-------------------------"
23
+ puts
24
+ end
25
+
26
+ # 上传一个object
27
+ # 流式上传请参考:examples/streaming.rb
28
+ demo "Put object from input" do
29
+ bucket.put_object('files/hello') do |content|
30
+ content << 'hello world.'
31
+ end
32
+ puts "Put object: files/hello"
33
+ end
34
+
35
+ # 上传一个文件
36
+ # 断点续传请参考:examples/resumable_upload.rb
37
+ demo "Put object from local file" do
38
+ File.open('/tmp/x', 'w'){ |f| f.write("hello world\n") }
39
+ bucket.put_object('files/world', :file => '/tmp/x')
40
+ puts "Put object: files/world"
41
+ end
42
+
43
+ # 创建一个Appendable object
44
+ demo "Create appendable object" do
45
+ size = bucket.get_object('files/appendable').size rescue 0
46
+ bucket.append_object('files/appendable', size) do |content|
47
+ content << 'hello appendable.'
48
+ end
49
+ puts "Append object: files/appendable"
50
+ end
51
+
52
+ # 向files/appendable中追加内容
53
+ # 首先要获取object当前的长度
54
+ demo "Append to object" do
55
+ size = bucket.get_object('files/appendable').size
56
+ bucket.append_object('files/appendable', size) do |content|
57
+ content << 'again appendable.'
58
+ end
59
+ puts "Append object: files/appendable"
60
+ end
61
+
62
+ # 使用错误的position进行追加会失败
63
+ demo "Append with wrong pos" do
64
+ begin
65
+ bucket.append_object('files/appendable', 0) do |content|
66
+ content << 'again appendable.'
67
+ end
68
+ rescue => e
69
+ puts "Append failed: #{e.message}"
70
+ end
71
+ end
72
+
73
+ # 向一个normal object中追加内容会失败
74
+ demo "Append to normal object(fail)" do
75
+ begin
76
+ bucket.append_object('files/hello', 0) do |content|
77
+ content << 'hello appendable.'
78
+ end
79
+ rescue => e
80
+ puts "Append object failed: #{e.message}"
81
+ end
82
+ end
83
+
84
+ # 拷贝一个object
85
+ demo "Copy object" do
86
+ bucket.copy_object('files/hello', 'files/copy')
87
+ puts "Copy object files/hello => files/copy"
88
+ end
89
+
90
+ # 拷贝一个appendable object会失败
91
+ demo "Copy appendable object(fail)" do
92
+ begin
93
+ bucket.copy_object('files/appendable', 'files/copy')
94
+ rescue => e
95
+ puts "Copy object failed: #{e.message}"
96
+ end
97
+ end
98
+
99
+ # 下载一个object:流式处理
100
+ # 流式下载请参考:examples/streaming.rb
101
+ demo "Get object: handle content" do
102
+ total_size = 0
103
+ bucket.get_object('files/hello') do |chunk|
104
+ total_size += chunk.size
105
+ end
106
+ puts "Total size: #{total_size}"
107
+ end
108
+
109
+ # 下载一个object:下载到文件中
110
+ demo "Get object to local file" do
111
+ bucket.get_object('files/hello', :file => '/tmp/hello')
112
+ puts "Get object: files/hello => /tmp/hello"
113
+ end
114
+
115
+ # 删除一个object
116
+ demo "Delete object" do
117
+ bucket.delete_object('files/world')
118
+ puts "Delete object: files/world"
119
+ end
120
+
121
+ # 删除一个不存在的object返回OK
122
+ # 这意味着delete_object是幂等的,在删除失败的时候可以不断重试,直到成
123
+ # 功,成功意味着object已经不存在
124
+ demo "Delete a non-existent object(OK)" do
125
+ bucket.delete_object('non-existent-object')
126
+ puts "Delete object: non-existent-object"
127
+ end
128
+
129
+ # 设置Object metas
130
+ demo "Put objec with metas" do
131
+ bucket.put_object(
132
+ 'files/hello',
133
+ :metas => {'year' => '2015', 'people' => 'mary'}
134
+ ) do |content|
135
+ content << 'hello world.'
136
+ end
137
+
138
+ o = bucket.get_object('files/hello', :file => '/tmp/x')
139
+ puts "Object metas: #{o.metas}"
140
+ end
141
+
142
+ # 修改Object metas
143
+ demo "Update object metas" do
144
+ bucket.update_object_metas(
145
+ 'files/hello', {'year' => '2016', 'people' => 'jack'})
146
+ o = bucket.get_object('files/hello')
147
+ puts "Meta changed: #{o.metas}"
148
+ end
149
+
150
+ # 设置Object的ACL
151
+
152
+ demo "Set object ACL" do
153
+ puts "Object acl before: #{bucket.get_object_acl('files/hello')}"
154
+ bucket.set_object_acl('files/hello', AliyunSDK::OSS::ACL::PUBLIC_READ)
155
+ puts "Object acl now: #{bucket.get_object_acl('files/hello')}"
156
+ end
157
+
158
+ # 指定条件get_object
159
+ demo "Get object with conditions" do
160
+ o = bucket.get_object('files/hello')
161
+
162
+ begin
163
+ o = bucket.get_object(
164
+ 'files/hello',
165
+ :condition => {:if_match_etag => o.etag + 'x'})
166
+ rescue AliyunSDK::OSS::ServerError => e
167
+ puts "Get object failed: #{e.message}"
168
+ end
169
+
170
+ begin
171
+ o = bucket.get_object(
172
+ 'files/hello',
173
+ :condition => {:if_unmodified_since => o.last_modified - 60})
174
+ rescue AliyunSDK::OSS::ServerError => e
175
+ puts "Get object failed: #{e.message}"
176
+ end
177
+
178
+ o = bucket.get_object(
179
+ 'files/hello',
180
+ :condition => {:if_match_etag => o.etag, :if_unmodified_since => Time.now})
181
+ puts "Get object: #{o.to_s}"
182
+ end
@@ -0,0 +1,42 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__))
4
+ require 'yaml'
5
+ require 'aliyun/oss'
6
+
7
+ # 初始化OSS Bucket
8
+ AliyunSDK::Common::Logging.set_log_level(Logger::DEBUG)
9
+ conf_file = '~/.oss.yml'
10
+ conf = YAML.load(File.read(File.expand_path(conf_file)))
11
+ bucket = AliyunSDK::OSS::Client.new(
12
+ :endpoint => conf['endpoint'],
13
+ :cname => conf['cname'],
14
+ :access_key_id => conf['access_key_id'],
15
+ :access_key_secret => conf['access_key_secret']).get_bucket(conf['bucket'])
16
+
17
+ # 辅助打印函数
18
+ def demo(msg)
19
+ puts "######### #{msg} ########"
20
+ puts
21
+ yield
22
+ puts "-------------------------"
23
+ puts
24
+ end
25
+
26
+ demo "Resumable download" do
27
+ # 下载一个100M的文件
28
+ cpt_file = '/tmp/y.cpt'
29
+ File.delete(cpt_file) if File.exist?(cpt_file)
30
+ start = Time.now
31
+ puts "Start download: resumable => /tmp/y"
32
+ bucket.resumable_download(
33
+ 'resumable', '/tmp/y', :cpt_file => cpt_file) do |progress|
34
+ puts "Progress: #{(progress * 100).round(2)} %"
35
+ end
36
+ puts "Download complete. Cost: #{Time.now - start} seconds."
37
+
38
+ # 测试方法:
39
+ # 1. ruby examples/resumable_download.rb
40
+ # 2. 过几秒后用Ctrl-C中断下载
41
+ # 3. ruby examples/resumable_download.rb恢复下载
42
+ end
@@ -0,0 +1,49 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ $LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__))
4
+ require 'yaml'
5
+ require 'aliyun/oss'
6
+
7
+ # 初始化OSS Bucket
8
+ AliyunSDK::Common::Logging.set_log_level(Logger::DEBUG)
9
+ conf_file = '~/.oss.yml'
10
+ conf = YAML.load(File.read(File.expand_path(conf_file)))
11
+ bucket = AliyunSDK::OSS::Client.new(
12
+ :endpoint => conf['endpoint'],
13
+ :cname => conf['cname'],
14
+ :access_key_id => conf['access_key_id'],
15
+ :access_key_secret => conf['access_key_secret']).get_bucket(conf['bucket'])
16
+
17
+ # 辅助打印函数
18
+ def demo(msg)
19
+ puts "######### #{msg} ########"
20
+ puts
21
+ yield
22
+ puts "-------------------------"
23
+ puts
24
+ end
25
+
26
+ demo "Resumable upload" do
27
+ puts "Generate file: /tmp/x, size: 100MB"
28
+ # 生成一个100M的文件
29
+ File.open('/tmp/x', 'w') do |f|
30
+ (1..1024*1024).each{ |i| f.puts i.to_s.rjust(99, '0') }
31
+ end
32
+
33
+ cpt_file = '/tmp/x.cpt'
34
+ File.delete(cpt_file) if File.exist?(cpt_file)
35
+
36
+ # 上传一个100M的文件
37
+ start = Time.now
38
+ puts "Start upload: /tmp/x => resumable"
39
+ bucket.resumable_upload(
40
+ 'resumable', '/tmp/x', :cpt_file => cpt_file) do |progress|
41
+ puts "Progress: #{(progress * 100).round(2)} %"
42
+ end
43
+ puts "Upload complete. Cost: #{Time.now - start} seconds."
44
+
45
+ # 测试方法:
46
+ # 1. ruby examples/resumable_upload.rb
47
+ # 2. 过几秒后用Ctrl-C中断上传
48
+ # 3. ruby examples/resumable_upload.rb恢复上传
49
+ end