aliyun-oss-ruby-sdk 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
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