aliyunoss 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0859a2ea3ada1c1b72d5aa4bf7c19b475f2eee2
4
- data.tar.gz: 3097869be179d2db30cf5c62cbac7f30994bc0bc
3
+ metadata.gz: 5cc87c05e0eb083f64578345b86b05f6734f6bca
4
+ data.tar.gz: 2f38f52a10c1c692d9d91c5466eb2690f75167f1
5
5
  SHA512:
6
- metadata.gz: dedf4b7a770d1cf47d24433121c873906be73773d80910a018f445f7e61a50eb9dba647d824d36747275113cb3ef9e6467d4bd6bb90657aff484ab8ee678f062
7
- data.tar.gz: cf277b1cb70111c855c9a997e523940d5198f60290196db1b67c8bd6b4d3ae755e96dd5a9768bde540490c035f386b7668c5c31f08429a1f65ee5f24b600781c
6
+ metadata.gz: 6bf9a1f3732ab56243a38a98d74f03d6eabad29b81aa928440c764613cb4a4e76da598a6a11859567b944c6310ab22387e40fb5d31b1c2c39ac7b325dbd918a7
7
+ data.tar.gz: 5a0b80b464be4ce629fbe9eccfa543c41b916c68cfddaffa7d34c05026e9701e70cc9f828cee93a60e50ed198756b19506ce365c5fc1adc197884931df476ba1
data/.byebug_history ADDED
@@ -0,0 +1,15 @@
1
+ q
2
+ Aliyun::Oss.config[:logger].info 'xxxx'
3
+ Aliyun::Oss.config[:logger]
4
+ Aliyun::Oss.config
5
+ Aliyun::Oss.logger
6
+ Aliyun::Oss.configure(logger: Logger.new(STDOUT))
7
+ Aliyun::Oss.logger
8
+ Aliyun::Oss.configure.logger
9
+ Aliyun::Oss.configure.log
10
+ q
11
+ @config[:logger]
12
+ c
13
+ @config[:logger]
14
+ c
15
+ @config[:logger]
data/.gitignore CHANGED
@@ -13,4 +13,5 @@
13
13
  *.a
14
14
  mkmf.log
15
15
  *~
16
- aliyun-config.yml
16
+ aliyun-config.yml
17
+ *.gem
data/Gemfile CHANGED
@@ -3,4 +3,6 @@ source 'https://ruby.taobao.org/'
3
3
  # Specify your gem's dependencies in aliyun-oss.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'nokogiri'
7
+
6
8
  gem 'byebug', :group => ['development', 'test']
data/README.md CHANGED
@@ -2,7 +2,29 @@
2
2
 
3
3
  Ruby gem for [Aliyun Open Storage Service (OSS)][1]. This gem implemented API from [references of Aliyun OSS-API][2].
4
4
 
5
- ## Installation
5
+ ## Table of Contents
6
+
7
+ * [Installation](#installation)
8
+ * [Usage](#usage)
9
+ * [Load Access Key ID and Access Key Secrete](#load)
10
+ * [Get Log Messages](#setlog)
11
+ * [Using Bucket API](#highlevel)
12
+ * [List Buckets](#listbuckets)
13
+ * [Create a Bucket](#newbucket)
14
+ * [Open a Bucket](#openbucket)
15
+ * [List Files In Bucket](#listfiles)
16
+ * [Upload a File to Bucket](#uploadfile)
17
+ * [Download a File from Bucket](#downloadfile)
18
+ * [Share a File in Bucket](#sharefile)
19
+ * [Delete a File in Bucket](#deletefile)
20
+ * [Upload a Large File in Multipart Way](#uploadlargefile)
21
+ * [Delete a bucket](#deletebucket)
22
+ * [Enable/Disable Logging for bucket](#logging)
23
+ * [Using Primitive API](#lowlevel)
24
+ * [Test](#test)
25
+ * [Contribute](#contribute)
26
+
27
+ ## <a name="installation"></a>Installation
6
28
 
7
29
  Add this line to your application's Gemfile:
8
30
 
@@ -12,73 +34,258 @@ gem 'aliyunoss'
12
34
 
13
35
  And then execute:
14
36
 
15
- $ bundle
37
+ ```ruby
38
+ $ bundle
39
+ ```
16
40
 
17
41
  Or install it yourself as:
18
42
 
19
- $ gem install aliyunoss
43
+ ```ruby
44
+ $ gem install aliyunoss
45
+ ```
20
46
 
21
- ## Usage
47
+ ## <a name="usage"></a>Usage
22
48
 
23
- This gem provides high level interfaces which are built around class Bucket and low level interfaces which are wrappers for [OSS API][2].
49
+ This gem provides Bucket API which are built around class Bucket and Primitive API which are wrappers for [OSS API][2]. Most of time using Bucket API is OK except you find OSS API that I didn't implement.
24
50
 
25
- ### Load Access Key ID and Access Key Secret
51
+ ### <a name="load"></a>Load Access Key ID and Access Key Secret
26
52
 
27
53
  Specify you access key and access secret before calling methods provided in this gem:
28
54
 
29
- Aliyun::Oss::configure(:access_key_id => 'access key id from aliyun', :access_key_secret => 'access secret from aliyun')
55
+ ```ruby
56
+ Aliyun::Oss::configure(:access_key_id => 'access key id from aliyun', :access_key_secret => 'access secret from aliyun')
57
+ ```
58
+
59
+ When using this gem in a rails project, you can create a file named 'aliyunoss_key.rb' in RAILS\_ROOT/config/initializers, whose content is:
30
60
 
31
- ### Low Level Interfaces
61
+ ```ruby
62
+ Aliyun::Oss::configure(:access_key_id => 'access key id from aliyun', :access_key_secret => 'access secret from aliyun')
63
+ ```
64
+
65
+ Then you can use the following APIs anywhere.
32
66
 
33
- Low level interfaces are simple wrappers for [OSS API][2], you send requests with specified parameters and receive responses with a Net::HTTPResponse object. All parameters listed in [OSS API][2] are needed for every request, and context info between requests is maintained by yourself. In order to tell whether a a request is success, check code and body of returned Net::HTTPResponse object.
67
+ ### <a name="setlog"></a>Get Log Messages
34
68
 
35
- All [OSS API][2] listed are implemented except [Post Object][3] and [CORS APIs][4].
69
+ Log message is prohibited by default, you can pass a logger instace to enable it:
36
70
 
37
- List all the buckets:
71
+ ```ruby
72
+ Aliyun::Oss::configure(:logger => Logger.new(STDOUT))
73
+ ```
38
74
 
39
- Aliyun::Oss::API.list_bucket
75
+ ### <a name="highlevel"></a>Bucket API
40
76
 
41
- Upload data to specified bucket:
77
+ Bucket API are built around class Bucket. You create a new bucket, and upload, download or delete files in it. When needed, responses are parsed to array, hash or object etc, thus more meaningful. Exceptions will be raised when request failed.
42
78
 
43
- bucket = Aliyun::Oss::Bucket.new(:name => 'bucket-name', :location => 'oss-cn-beijing')
44
- path = '/test.dat'
45
- data = Random.new.bytes(1024 * rand(100..300))
46
- Aliyun::Oss::API.put_object(bucket, path, data)
79
+ ```ruby
80
+ # Create a bucket in OSS server
81
+ bucket = Aliyun::Oss::Bucket.create('aliyun-oss-gem-api-test','oss-cn-hangzhou')
82
+
83
+ # Upload a file
84
+ filename = '/some/file'
85
+ bucket.upload( IO.read(filename) )
86
+
87
+ # List all files in this bucket, returns a Hash array containing files info
88
+ files = bucket.list_files
89
+
90
+ # Download a file, returns raw data
91
+ data = bucket.download( '/some/path' )
92
+ ```
93
+
94
+ #### <a name="listbuckets"></a>List all buckets
47
95
 
48
- Download data from specified bucket:
96
+ After correctly configuring your access key and secret, you can list all buckets:
49
97
 
50
- bucket = Bucket.new(:name => 'bucket-name', :location => 'oss-cn-beijing')
51
- path = '/test.dat'
52
- Aliyun::Oss::API.get_object(bucket, path)
98
+ ```ruby
99
+ Aliyun::Oss::Bucket.all
100
+ ```
53
101
 
54
- For more usage, see API documentation generated by rdoc.
102
+ The result is a Bucket array. Class Bucket has some simple attributes :
55
103
 
56
- ### High Level Interfaces
104
+ ```ruby
105
+ class Bucket
106
+ attr_accessor :location, :name, :creation_date, :domain, :extranet_endpoint, :intranet_endpoint
107
+ # ...
108
+ end
109
+ ```
57
110
 
58
- High level interface are built around class Bucket. You create a new bucket, and upload, download or delete files in it. When needed, responses are parsed to array, hash or object etc, thus more meaningful. Exceptions will be raised when request failed.
111
+ #### <a name="newbucket"></a>Create a new bucket
59
112
 
60
- # Create a bucket in OSS server
61
- bucket = Aliyun::Oss::Bucket.create('aliyun-oss-gem-api-test','oss-cn-hangzhou')
62
-
63
- # Upload a file
64
- filename = '/some/file'
65
- bucket.upload( IO.read(filename) )
66
-
67
- # List all files in this bucket, returns a Hash array containing files info
68
- files = bucket.list_files
113
+ You can create a new bucket using class method *create* of Bucket:
114
+
115
+ ```ruby
116
+ bucket = Aliyun::Oss::Bucket.create(bucket_name, bucket_location)
117
+ ```
69
118
 
70
- # Download a file, returns raw data
71
- data = bucket.download( '/some/path' )
119
+ Where *bucket_name* is a string, and *bucket_location* is an optional string parameter which defaults to 'oss-cn-hangzhou'. Other available bucket locations can be referenced [here][5]. This method return a new Bucket instance if success.
120
+
121
+ #### <a name="openbucket"></a>Open a bucket
122
+
123
+ There is no such opeartion as opening a bucket, but you can create a Bucket instance by:
124
+
125
+ ```ruby
126
+ Aliyun::Oss::Bucket.new(name: 'bucket-name', location: 'oss-cn-beijing')
127
+ ```
128
+
129
+ So you can continue to download or upload files using this Bucket instance.
130
+
131
+ #### <a name="listfiles"></a>List all files in an bucket
132
+
133
+ You can list all files in an bucket using instance method *list\_files* of a bucket:
134
+
135
+ ```ruby
136
+ files = bucket.list_files
137
+ ```
138
+
139
+ The result is a array consisted of file objects which are parsed from xml reponse, eg.
140
+
141
+ ```ruby
142
+ [
143
+ { "key"=>"100f1a845046c189944dc8fd57bffbe390b90e3a.png",
144
+ "last_modified"=>"2015-12-14T03:04:37.000Z",
145
+ "e_tag"=>"\"B9072ECBBF4B06962517B3FD4090538E\"",
146
+ "type"=>"Normal",
147
+ "size"=>"49509",
148
+ "storage_class"=>"Standard" },
149
+
150
+ { "key"=>"11c5db2a88648d25da889a1d20687ec535a50905.jpg",
151
+ "last_modified"=>"2015-12-14T08:03:54.000Z",
152
+ "e_tag"=>"\"77618F54695C08E278ACBD7D9C63E521\"",
153
+ "type"=>"Normal",
154
+ "size"=>"491133",
155
+ "storage_class"=>"Standard" }
156
+ ]
157
+ ```
158
+
159
+ #### <a name="uploadfile"></a>Upload a file to bucket
160
+
161
+ You can upload a file using instance method *upload* of a bucket, eg.
162
+
163
+ ```ruby
164
+ data = IO.read('/local/path/of/file')
165
+ bucket.upload(data, '/remote/path/of/file')
166
+ ```
167
+
168
+ This will raise an exception unless success. A file in remote bucket can include some meta data, eg. when serving images, we often want Aliyun OSS server to return *Content-Type* header for http GET request. To acheive this effect, we have to add additional paramters when uploading file, eg.
169
+
170
+ ```ruby
171
+ image = IO.read('/local/image')
172
+ bucket.upload(image, '/remote/image', 'Content-Type'=>'image/png')
173
+ ```
174
+
175
+ #### <a name="downloadfile"></a>Download file from bucket
176
+
177
+ You can read content of a remote file using instance method *download* of a bucket, eg.
178
+
179
+ ```ruby
180
+ raw_data = bucket.download('/remote/path/of/file')
181
+ ```
182
+
183
+ where *raw_data* is body of a Net::HTTPResponse object.
184
+
185
+ #### <a name="sharefile"></a>Generate a sharing url of a remote file
186
+
187
+ If you set your bucket private for reading, others cannot access content of files in your bucket without valid access key and secret. But you won't give them access key or secret, instead you generate a sharing url for them to access your file:
188
+
189
+ ```ruby
190
+ public_url = bucket.share('/remote/file')
191
+ ```
72
192
 
73
- For more usage, see API documentation generated by rdoc.
193
+ This will generate a public url that can access some remote file. By default this url is only valid for 1 hour, you can change this behavior by adding the second paramter:
194
+
195
+ ```ruby
196
+ public_url = bucket.share('/remote/file', 60 * 60 * 24)
197
+ ```
198
+
199
+ where unit used is second, so that will be 1 day long.
200
+
201
+ #### <a name="deletefile"></a>Delete a file in the bucket
202
+
203
+ You can delete a remote file using instance method *delete* of a bucket, eg:
204
+
205
+ ```ruby
206
+ bucket.delete('/remote/path/of/file')
207
+ ```
74
208
 
75
- ## Testing
209
+ It will return an Net::HTTPNoContent if file is deleted successfully OR file not found.
210
+
211
+ #### <a name="uploadlargefile"></a>Upload a large file in multipart way
212
+
213
+ When uploading a large file, using multipart way is preffered due to unreliable network condition. An multipart task consist of a sequence operations: *multipart\_upload\_initiate*, *multipart\_upload* and *multipart_upload_compelete*:
214
+
215
+ ```ruby
216
+ bucket.multipart_upload_initiate('/remote/path/of/a/large/file')
217
+
218
+ 10.times do
219
+ bucket.multipart_upload( Random.new.bytes(1024 * rand(100..300)) )
220
+ end
221
+
222
+ bucket.multipart_upload_complete
223
+ ```
224
+
225
+ #### <a name="deletebucket"></a>Delete a bucket
226
+
227
+ You can delete a bucket using instance method *delete!* of a bucket, eg:
228
+
229
+ ```ruby
230
+ bucket.delete!
231
+ ```
232
+
233
+ Exception will be raised unless bucket is empty.
234
+
235
+ #### <a name="logging"></a>Enable/Disable logging for a bucket
236
+
237
+ OSS can record access log for a bucket, you can toggle this function by:
238
+
239
+ ```ruby
240
+ bucket.enable_logging('/remote/file/of/log', 'log_prefix')
241
+ ```
242
+
243
+ Then all access log is recorded with prefix you specified with the second paramter, and stored in the path you specified by the first parameter.
244
+
245
+ Disable this function by:
246
+
247
+ ```ruby
248
+ bucket.disable_logging
249
+ ```
250
+
251
+ ### <a name="lowlevel"></a>Primitive API
252
+
253
+ Primitive API are simple http wrappers for [OSS API][2], you send requests with specified parameters and receive responses with a Net::HTTPResponse object. All parameters listed in [OSS API][2] are needed for every request, and context information between requests is maintained by yourself. In order to tell whether a a request is success, check code and body of returned Net::HTTPResponse object.
254
+
255
+ All [OSS API][2] listed are implemented except [Post Object][3] and [CORS APIs][4].
256
+
257
+ List all the buckets:
258
+
259
+ ```ruby
260
+ Aliyun::Oss::API.list_bucket
261
+ ```
262
+
263
+ Upload data to specified bucket:
264
+
265
+ ```ruby
266
+ bucket = Aliyun::Oss::Bucket.new(:name => 'bucket-name', :location => 'oss-cn-beijing')
267
+ path = '/test.dat'
268
+ data = Random.new.bytes(1024 * rand(100..300))
269
+ Aliyun::Oss::API.put_object(bucket, path, data)
270
+ ```
271
+
272
+ Download data from specified bucket:
273
+
274
+ ```ruby
275
+ bucket = Bucket.new(:name => 'bucket-name', :location => 'oss-cn-beijing')
276
+ path = '/test.dat'
277
+ Aliyun::Oss::API.get_object(bucket, path)
278
+ ```
279
+
280
+ For more usage, see API documentation generated by rdoc.
281
+
282
+ ## <a name="test"></a>Testing
76
283
 
77
284
  This gem use rspec for testing. Most of testing needs a valid access key id and access key secret, you should get these info from Aliyun.
78
285
 
79
286
  Create a file named aliyun-config.yml in path rspec/aliyunoss/config, fill in valid access key id and access key secret and cotinue to test.
80
287
 
81
- ## Contributing
288
+ ## <a name="contribute"></a>Contributing
82
289
 
83
290
  1. Fork it ( https://github.com/yijiecc/aliyunoss/fork )
84
291
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -86,7 +293,8 @@ Create a file named aliyun-config.yml in path rspec/aliyunoss/config, fill in va
86
293
  4. Push to the branch (`git push origin my-new-feature`)
87
294
  5. Create a new Pull Request
88
295
 
89
- [1]: http://www.aliyun.com/product/oss
90
- [2]: http://docs.aliyun.com/?spm=5176.383663.9.2.F8rxxr#/oss/api-reference/abstract
91
- [3]: http://docs.aliyun.com/?spm=5176.383663.9.2.F8rxxr#/oss/api-reference/object&PostObject
92
- [4]: http://docs.aliyun.com/?spm=5176.383663.9.2.F8rxxr#/oss/api-reference/cors&abstract
296
+ [1]: https://www.aliyun.com/product/oss?spm=5176.doc31870.416540.44.QdQVwH
297
+ [2]: https://help.aliyun.com/document_detail/31827.html?spm=5176.doc31817.6.564.Px1zOr
298
+ [3]: https://help.aliyun.com/document_detail/31849.html?spm=5176.doc31827.6.581.XDg3ZS
299
+ [4]: https://help.aliyun.com/document_detail/31870.html?spm=5176.87240.400427.34.vFnPt8
300
+ [5]: https://help.aliyun.com/document_detail/31837.html?spm=5176.doc31959.2.1.EpUpfD
data/lib/aliyunoss.rb CHANGED
@@ -1,8 +1,13 @@
1
+ #
1
2
  # dependency
3
+ #
2
4
  require 'nokogiri'
3
5
  require 'net/http'
4
6
  require 'logger'
5
7
 
8
+ #
9
+ # aliyunoss files
10
+ #
6
11
  require 'aliyunoss/config'
7
12
  require 'aliyunoss/config_helper'
8
13
  require 'aliyunoss/extension'
data/lib/aliyunoss/api.rb CHANGED
@@ -1,19 +1,23 @@
1
1
  module Aliyun
2
2
  module Oss
3
3
 
4
+ # Reference
5
+ # http://docs-aliyun-com-cn-b.oss-cn-hangzhou.aliyuncs.com/oss/pdf/oss_api-reference.pdf
4
6
  module API
5
7
  extend self
6
8
 
7
- # Reference
8
- # http://docs-aliyun-com-cn-b.oss-cn-hangzhou.aliyuncs.com/oss/pdf/oss_api-reference.pdf
9
9
 
10
+ #
10
11
  # List all buckets
12
+ #
11
13
  def list_bucket(params = {})
12
14
  Aliyun::Oss::OssRequest.new(nil, '/', nil, {}, {}).get
13
15
  end
14
16
  alias :get_service :list_bucket
15
17
 
18
+ #
16
19
  # Create a new bucket
20
+ #
17
21
  def put_bucket(name, location = 'oss-cn-hangzhou')
18
22
  bucket = Bucket.new(name: name, location: location)
19
23
  request = Aliyun::Oss::OssRequest.new(bucket, '/')
@@ -27,54 +31,74 @@ HERE
27
31
  end
28
32
  alias :create_bucket :put_bucket
29
33
 
34
+ #
30
35
  # Delete a bucket
36
+ #
31
37
  def delete_bucket(bucket)
32
38
  Aliyun::Oss::OssRequest.new(bucket, '/').delete
33
39
  end
34
-
40
+
41
+ #
35
42
  # Delete bucket logging
43
+ #
36
44
  def delete_logging(bucket)
37
45
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'logging'=>nil).delete
38
46
  end
39
47
 
48
+ #
40
49
  # Delete bucket website
50
+ #
41
51
  def delete_website(bucket)
42
52
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'website'=>nil).delete
43
53
  end
44
54
  alias :disable_website :delete_website
45
55
 
56
+ #
46
57
  # List objects in bucket
58
+ #
47
59
  def list_object(bucket, queries = {})
48
60
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, queries).get
49
61
  end
50
62
 
63
+ #
51
64
  # Get bucket acl
65
+ #
52
66
  def get_bucket_acl(bucket)
53
67
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'acl'=>nil).get
54
68
  end
55
69
 
70
+ #
56
71
  # Get bucket location
72
+ #
57
73
  def get_bucket_location(bucket)
58
74
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'location'=>nil).get
59
75
  end
60
76
 
77
+ #
61
78
  # Query bucket logging status
79
+ #
62
80
  def get_bucket_logging(bucket)
63
81
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'logging'=>nil).get
64
82
  end
65
83
 
84
+ #
66
85
  # Query bucket website status
86
+ #
67
87
  def get_bucket_website(bucket)
68
88
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'website'=>nil).get
69
89
  end
70
90
 
91
+ #
71
92
  # Set bucket acl permission
93
+ #
72
94
  def put_bucket_acl(bucket, permission)
73
95
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, {}, 'x-oss-acl'=> permission).put
74
96
  end
75
97
  alias :set_bucket_acl :put_bucket_acl
76
98
 
77
- # Enable or disable bucket logging
99
+ #
100
+ # Enable bucket logging
101
+ #
78
102
  def enable_bucket_logging(bucket, bucket_name_for_logging, log_prefix)
79
103
  request = Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'logging'=>nil)
80
104
  request.body = <<HERE
@@ -90,6 +114,9 @@ HERE
90
114
  request.put
91
115
  end
92
116
 
117
+ #
118
+ # Disable bucket logging
119
+ #
93
120
  def disable_bucket_logging(bucket)
94
121
  request = Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'logging'=>nil)
95
122
  request.body = <<HERE
@@ -101,7 +128,9 @@ HERE
101
128
  request.put
102
129
  end
103
130
 
131
+ #
104
132
  # Set bucket website access
133
+ #
105
134
  def put_bucket_website(bucket, index_page, error_page)
106
135
  request = Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'website'=>nil)
107
136
  request.body = <<HERE
@@ -119,19 +148,25 @@ HERE
119
148
  request.put
120
149
  end
121
150
  alias :set_bucket_website :put_bucket_website
122
-
151
+
152
+ #
123
153
  # Copy Object
154
+ #
124
155
  def copy_object(source_bucket, source_path, target_bucket, target_path, headers = {})
125
156
  headers = headers.merge({'x-oss-copy-source'=> "/" + source_bucket.name + source_path})
126
157
  Aliyun::Oss::OssRequest.new(target_bucket, target_path, nil, {}, headers).put
127
158
  end
128
159
 
160
+ #
129
161
  # Delete Object
162
+ #
130
163
  def delete_object(bucket, path)
131
164
  Aliyun::Oss::OssRequest.new(bucket, path).delete
132
165
  end
133
166
 
167
+ #
134
168
  # Delete Multiple Object
169
+ #
135
170
  def delete_multiple_objects(bucket, objects, quiet_mode = false)
136
171
  xml = '<?xml version="1.0" encoding="UTF-8"?>'
137
172
  xml << '<Delete>'
@@ -143,48 +178,70 @@ HERE
143
178
  request.post
144
179
  end
145
180
 
181
+ #
146
182
  # Get Object
183
+ #
147
184
  def get_object(bucket, path, headers = {})
148
185
  Aliyun::Oss::OssRequest.new(bucket, path, nil, {}, headers).get
149
186
  end
150
187
 
188
+ #
151
189
  # Head Object
190
+ #
152
191
  def head_object(bucket, path, headers = {})
153
192
  Aliyun::Oss::OssRequest.new(bucket, path, nil, {}, headers).head
154
193
  end
155
194
 
195
+ #
156
196
  # Put Object
197
+ #
157
198
  def put_object(bucket, path, data, headers = {})
158
199
  request = Aliyun::Oss::OssRequest.new(bucket, path, nil, {}, headers)
159
200
  request.body = data
160
201
  request.put
161
202
  end
162
203
 
204
+ #
163
205
  # get share url for specified object
206
+ #
164
207
  def generate_share_url(bucket, path, expires_in = 3600)
165
208
  Aliyun::Oss::OssRequest.new(bucket, path).url_for_sharing(expires_in)
166
209
  end
167
210
 
211
+ #
168
212
  # Post Object
213
+ #
169
214
  # Not implemented
170
215
 
216
+ #
171
217
  # Post Policy
218
+ #
172
219
  # Not implemented
173
220
 
221
+ #
174
222
  # Post signature
223
+ #
175
224
  # Not implemented
176
225
 
226
+ #
177
227
  # Multipart Initiate
228
+ #
178
229
  def multipart_upload_initiate(bucket, path)
179
230
  Aliyun::Oss::OssRequest.new(bucket, path, nil, 'uploads'=>nil).post
180
231
  end
181
232
 
233
+ #
234
+ # Multipart upload part
235
+ #
182
236
  def multipart_upload_part(bucket, path, upload_id, data, part_number)
183
237
  request = Aliyun::Oss::OssRequest.new(bucket, path, nil, 'partNumber'=> part_number.to_s, 'uploadId'=> upload_id)
184
238
  request.body = data
185
239
  request.put
186
240
  end
187
241
 
242
+ #
243
+ # Multipart upload from copy
244
+ #
188
245
  def multipart_upload_from_copy(upload_id, source_bucket, source_path, target_bucket, target_path, part_number, part_size, range = nil)
189
246
  request = Aliyun::Oss::OssRequest.new(target_bucket, target_path, nil, 'partNumber'=> part_number.to_s, 'uploadId'=> upload_id)
190
247
  request['Content-Length'] = part_size
@@ -193,6 +250,9 @@ HERE
193
250
  request.put
194
251
  end
195
252
 
253
+ #
254
+ # Complete an multipart upload.
255
+ #
196
256
  def multipart_upload_complete(bucket, path, upload_id, part_list)
197
257
  request = Aliyun::Oss::OssRequest.new(bucket, path, nil, 'uploadId'=> upload_id)
198
258
  xml = '<?xml version="1.0" encoding="UTF-8"?>'
@@ -203,14 +263,23 @@ HERE
203
263
  request.post
204
264
  end
205
265
 
266
+ #
267
+ # Abort an upload task
268
+ #
206
269
  def multipart_upload_abort(bucket, path, upload_id)
207
270
  Aliyun::Oss::OssRequest.new(bucket, path, nil, 'uploadId'=> upload_id).delete
208
271
  end
209
272
 
273
+ #
274
+ # List finished multipart parts
275
+ #
210
276
  def multipart_upload_finished_parts(bucket, path, upload_id)
211
277
  Aliyun::Oss::OssRequest.new(bucket, path, nil, 'uploadId'=> upload_id).get
212
278
  end
213
279
 
280
+ #
281
+ # List all unfinished multipart task
282
+ #
214
283
  def multipart_upload_unfinished_task(bucket)
215
284
  Aliyun::Oss::OssRequest.new(bucket, '/', nil, 'uploads'=>nil).get
216
285
  end
@@ -12,40 +12,61 @@ module Aliyun
12
12
  end
13
13
  end
14
14
 
15
- # Class methods
15
+ #
16
+ # Class method - List all buckets in my account
17
+ #
16
18
  def self.all
17
19
  Aliyun::Oss::API.list_bucket.raise_unless(Net::HTTPOK).to_buckets
18
20
  end
19
21
 
22
+ #
23
+ # Class method - Create a new bucket
24
+ #
20
25
  def self.create(name, location = 'oss-cn-hangzhou')
21
26
  Aliyun::Oss::API.put_bucket(name, location).raise_unless(Net::HTTPOK)
22
27
  Bucket.new(:name => name, :location=> location, :creation_date => Time.now)
23
28
  end
24
29
 
25
- # Instance Methods -- object download and upload
30
+ #
31
+ # List all files in an bucket
32
+ #
26
33
  def list_files(options = {})
27
34
  Aliyun::Oss::API.list_object(self, options).raise_unless(Net::HTTPOK).to_objects
28
35
  end
29
36
 
37
+ #
38
+ # Upload data to bucket
39
+ #
30
40
  def upload(data, path, options = {})
31
41
  Aliyun::Oss::API.put_object(self, path, data, options).raise_unless(Net::HTTPOK)
32
42
  end
33
43
 
44
+ #
45
+ # Download file from remote server
46
+ #
34
47
  def download(path, options = {})
35
48
  Aliyun::Oss::API.get_object(self, path, options)
36
49
  .raise_unless(Net::HTTPOK)
37
50
  .body
38
51
  end
39
52
 
53
+ #
54
+ # Generate a url that can be shared to others
55
+ #
40
56
  def share(path, expires_in = 3600)
41
57
  Aliyun::Oss::API.generate_share_url(self, path, expires_in)
42
58
  end
43
59
 
60
+ #
61
+ # Delete remote file
62
+ #
44
63
  def delete(path)
45
64
  Aliyun::Oss::API.delete_object(self, path).raise_unless(Net::HTTPNoContent)
46
65
  end
47
66
 
67
+ #
48
68
  # Multipart upload and copy
69
+ #
49
70
  def multipart_pending
50
71
  Aliyun::Oss::API.multipart_upload_unfinished_task(self)
51
72
  .raise_unless(Net::HTTPOK)
@@ -95,7 +116,9 @@ module Aliyun
95
116
  @multipart_path = nil
96
117
  end
97
118
 
98
- # Instance Methods -- miscellaneous
119
+ #
120
+ # delete this bucket
121
+ #
99
122
  def delete!
100
123
  Aliyun::Oss::API.delete_bucket(self).raise_unless(Net::HTTPNoContent)
101
124
  end
@@ -1,22 +1,28 @@
1
1
  require 'yaml'
2
2
  require 'logger'
3
3
 
4
+ class NullLogger < Logger
5
+ def initialize(*args)
6
+ end
7
+
8
+ def add(*args, &block)
9
+ end
10
+ end
11
+
12
+
4
13
  module Aliyun
5
14
  module Oss
6
15
 
7
16
  @config = {
8
- :log_level => 'info',
17
+ :logger => nil,
9
18
  :host => 'aliyuncs.com',
10
19
  :access_key_id => nil,
11
20
  :access_key_secret => nil
12
21
  }
13
22
 
14
- @_logger = nil
15
-
16
23
  @valid_config_keys = @config.keys
17
24
 
18
25
  def self.configure(opts = {})
19
- @_logger = nil
20
26
  opts.each {|k,v| @config[k.to_sym] = v if @valid_config_keys.include?(k.to_sym)}
21
27
  end
22
28
 
@@ -36,11 +42,7 @@ module Aliyun
36
42
  end
37
43
 
38
44
  def self.logger
39
- unless @_logger
40
- @_logger ||= Logger.new(STDOUT)
41
- @_logger.level = Logger.const_get(@config[:log_level].upcase) rescue Logger::INFO
42
- end
43
- @_logger
45
+ @config[:logger] or (@null_logger ||= NullLogger.new)
44
46
  end
45
47
 
46
48
  end
@@ -25,10 +25,10 @@ class String
25
25
  # Convert CamelCase to ruby_case
26
26
  def underscore
27
27
  self.gsub(/::/, '/').
28
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
29
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
30
- tr("-", "_").
31
- downcase
28
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
29
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
30
+ tr("-", "_").
31
+ downcase
32
32
  end
33
33
 
34
34
  end
@@ -9,7 +9,10 @@ module Aliyun
9
9
 
10
10
  include ConfigHelper
11
11
  attr_accessor :bucket, :path, :body, :queris, :domain
12
-
12
+
13
+ #
14
+ # Create a new oss request, parameters will be sent to methods of Net::HTTP later.
15
+ #
13
16
  def initialize(bucket, path, domain = nil, queries = {}, headers = {})
14
17
  @bucket = bucket
15
18
  @path = path
@@ -18,6 +21,9 @@ module Aliyun
18
21
  @headers = {"Content-Type" => "", "Content-MD5" => "", "Date" => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')}.merge(headers)
19
22
  end
20
23
 
24
+ #
25
+ # Get complete url for this request
26
+ #
21
27
  def get_uri
22
28
  if @domain
23
29
  uri = URI("http://#{domain}/")
@@ -68,6 +74,9 @@ module Aliyun
68
74
  add_operation :head
69
75
  add_operation :post
70
76
 
77
+ #
78
+ # Get sharing url for this request, pass _expires_in_ as parameter.
79
+ #
71
80
  def url_for_sharing(expires_in)
72
81
  uri = get_uri
73
82
  request = Net::HTTP::Get.new(uri)
@@ -80,10 +89,16 @@ module Aliyun
80
89
  uri.to_s
81
90
  end
82
91
 
92
+ #
93
+ # Get http header value by attribute
94
+ #
83
95
  def [](key)
84
96
  @headers[key]
85
97
  end
86
98
 
99
+ #
100
+ # Set http header value by attribute
101
+ #
87
102
  def []=(key, value)
88
103
  @headers[key] = value
89
104
  end
@@ -1,5 +1,5 @@
1
1
  module Aliyun
2
2
  module Oss
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
  end
@@ -6,6 +6,7 @@ describe Aliyun::Oss::Bucket do
6
6
 
7
7
  before :all do
8
8
  Aliyun::Oss.configure_with('spec/aliyunoss/config/aliyun-config.yml')
9
+ Aliyun::Oss.configure(logger: Logger.new(STDOUT))
9
10
  @bucket_name = "aliyunoss-gem-test-#{rand.to_s.delete('0.')}"
10
11
  @location = 'oss-cn-beijing'
11
12
  @bucket = Aliyun::Oss::Bucket.new( location: @location, name: @bucket_name)
@@ -119,7 +120,7 @@ describe Aliyun::Oss::Bucket do
119
120
  end
120
121
 
121
122
  @bucket.delete!
122
- expect {Bucket.new(:name=> 'bucket_not_exist').delete!}.to raise_error
123
+ expect {Aliyun::Oss::Bucket.new(:name=> 'bucket_not_exist').delete!}.to raise_error(SocketError)
123
124
  end
124
125
 
125
126
  end
@@ -6,25 +6,22 @@ describe 'Aliyun::Oss Configuration' do
6
6
 
7
7
  before :each do
8
8
  config = Aliyun::Oss.config
9
- config[:log_level] = 'info'
10
9
  config[:access_key_id] = nil
11
10
  config[:access_key_secret] = nil
12
11
  end
13
12
 
14
13
  it 'should load default options' do
15
14
  default_config = Aliyun::Oss.config
16
- expect(default_config).to include(:log_level)
17
15
  expect(default_config).to include(:access_key_id)
18
16
  end
19
17
 
20
18
  it 'should accept configuration from #configure' do
21
19
  url = "http://bucket_name.region.aliyuncs.com"
22
20
  access_key = "access_key_from_aliyun"
23
- Aliyun::Oss.configure(:log_level => 'debug', :access_key_id => access_key, :not_used_para => "not used")
21
+ Aliyun::Oss.configure(:access_key_id => access_key, :not_used_para => "not used")
24
22
  config = Aliyun::Oss.config
25
23
  expect(config.keys).not_to include(:not_used_para)
26
24
  expect(config[:access_key_id]).to eq(access_key)
27
- expect(config[:log_level]).to eq('debug')
28
25
  end
29
26
 
30
27
  it 'should load yaml config file if specified' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aliyunoss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - yijiecc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-28 00:00:00.000000000 Z
11
+ date: 2018-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -73,6 +73,7 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - ".byebug_history"
76
77
  - ".gitignore"
77
78
  - Gemfile
78
79
  - LICENSE.txt
@@ -80,7 +81,6 @@ files:
80
81
  - Rakefile
81
82
  - aliyunoss.gemspec
82
83
  - lib/aliyunoss.rb
83
- - lib/aliyunoss/#oss_request.rb#
84
84
  - lib/aliyunoss/api.rb
85
85
  - lib/aliyunoss/bucket.rb
86
86
  - lib/aliyunoss/config.rb
@@ -120,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  version: '0'
121
121
  requirements: []
122
122
  rubyforge_project:
123
- rubygems_version: 2.4.8
123
+ rubygems_version: 2.6.14.1
124
124
  signing_key:
125
125
  specification_version: 4
126
126
  summary: A gem for accessing Aliyun Open Storage Service.
@@ -1,154 +0,0 @@
1
- # coding: utf-8
2
- require 'base64'
3
- require 'openssl'
4
-
5
- module Aliyun
6
- module Oss
7
-
8
- class OssRequest
9
-
10
- include ConfigHelper
11
- attr_accessor :bucket, :path, :body, :queris, :domain
12
-
13
- def initialize(bucket, path, domain = nil, queries = {}, headers = {})
14
- @bucket = bucket
15
- @path = path
16
- @queries = queries
17
- @domain = domain
18
- @headers = {"Content-Type" => "", "Content-MD5" => "", "Date" => Time.now.utc.strftime('%a, %d %b %Y %H:%M:%S GMT')}.merge(headers)
19
- end
20
-
21
- def get_uri
22
- if @domain
23
- uri = URI("http://#{domain}/")
24
- else
25
- if @bucket
26
- uri = URI("http://#{bucket.name}.#{bucket.location}.#{host}")
27
- else
28
- uri = URI("http://oss.#{host}")
29
- end
30
- end
31
- uri.path = @path
32
- uri.query = @queries.to_query_string if @queries.count > 0
33
- uri
34
- end
35
-
36
- def self.add_operation(verb)
37
- define_method(verb) do
38
- uri = get_uri
39
-
40
- request = Net::HTTP.send(:const_get, verb.to_s.capitalize).new(uri)
41
-
42
- @headers.each_pair {|k,v| request[k] = v}
43
-
44
- if @body
45
- request.body = @body
46
- digest = OpenSSL::Digest::MD5.digest(@body)
47
- request['Content-MD5'] = Base64.encode64(digest).strip
48
- request['Content-Length'] = @body.bytesize
49
- end
50
-
51
- request['Authorization'] = 'OSS ' + access_key_id + ':' +
52
- signature(request)
53
-
54
- logger.info(verb.to_s.upcase + ' ' + uri.to_s + ' ' + request.to_hash.to_s)
55
-
56
- response = nil
57
- Net::HTTP.start(uri.host, uri.port) do |http|
58
- response = http.request(request)
59
- logger.info(response.code.to_s + ' ' + response.message)
60
- end
61
- response
62
- end
63
- end
64
-
65
- add_operation :get
66
- add_operation :put
67
- add_operation :delete
68
- add_operation :head
69
- add_operation :post
70
-
71
- def url_for_sharing(expires_in)
72
- uri = get_uri
73
- request = Net::HTTP::Get.new(uri)
74
- @headers.each_pair {|k,v| request[k] = v}
75
- expires_at = (Time.now + expires_in).utc.to_i
76
- request["Date"] = expires_at
77
- uri.query = URI.encode_www_form({"OSSAccessKeyId" => access_key_id,
78
- "Expires" => expires_at,
79
- "Signature" => signature(request)})
80
- uri.to_s
81
- end
82
-
83
- def [](key)
84
- @headers[key]
85
- end
86
-
87
- def []=(key, value)
88
- @headers[key] = value
89
- end
90
-
91
- private
92
- def signature(req)
93
- verb = req.class.to_s.gsub(/Net::HTTP::/, '').upcase
94
- data = verb + "\n" + req["Content-MD5"] + "\n" +
95
- req["Content-Type"] + "\n" + req["Date"] + "\n" +
96
- canonicalized_oss_headers(req) +
97
- canonicalized_resource()
98
-
99
- digest = OpenSSL::Digest.new('sha1')
100
- hmac = OpenSSL::HMAC.digest(digest, access_key_secret, data)
101
- Base64.encode64(hmac).strip
102
- end
103
-
104
- # oss api 20140828.pdf - 4.2
105
- # 1) 将所有以“x-oss-”为前缀的 HTTP 请求头的名字转换成小写字母。如 ’X-OSS-Meta-Name: TaoBao’
106
- # 转换成 ’x-oss-meta-name: TaoBao’ 。
107
- # 2) 将上一步得到的所有 HTTP 请求头按照字典序进行升序排列。
108
- # 3) 如果有相同名字的请求头,则根据标准 RFC 2616, 4.2 章进行合并(两个值之间只用逗号分隔)。
109
- # 如有两个名为’x-oss-meta-name’的请求头,对应的值分别为’TaoBao’和’Alipay’,则合并后
110
- # 为: ’x-oss-meta-name:TaoBao,Alipay’ 。
111
- # 4) 删除请求头和内容之间分隔符两端出现的任何空格。
112
- # 如 ’x-oss-meta-name: TaoBao,Alipay’ 转换成: ’x-oss-meta-name:TaoBao,Alipay’ 。
113
- # 5) 将所有的头和内容用 ’\n’ 分隔符分隔拼成最后的 CanonicalizedOSSHeader 。
114
- def canonicalized_oss_headers(req)
115
- hash = Hash.new
116
- req.each_header do |header|
117
- header = header.downcase
118
- next unless header.start_with?('x-oss-')
119
- if hash.has_key?(header)
120
- hash[header] = hash[header] + "," + req[header].strip
121
- else
122
- hash[header] = req[header].strip
123
- end
124
- end
125
-
126
- return "" if hash.count == 0
127
- hash.keys.sort.map{|k| "#{k}:#{hash[k]}"}.join("\n") << "\n"
128
- end
129
-
130
- # oss api 20140828.pdf - 4.2
131
- # 1) 将 CanonicalizedResource 置成空字符串( “” );
132
- # 2) 放入要访问的 OSS 资源:“ /BucketName/ObjectName ”(无 ObjectName 则不填)
133
- # 3) 如果请求的资源包括子资源 (sub-resource) ,那么将所有的子资源按照字典序,从小到大排列并
134
- # 以 ’&’ 为分隔符生成子资源字符串。在 CanonicalizedResource 字符串尾添加“?”和子资源字
135
- # 符串。此时的 CanonicalizedResource 例子如: /BucketName/ObjectName?acl &uploadId=UploadId
136
- # 4) 如果用户请求在查询字符串 (query string) 中指定了要重写 (override) 返回请求的 header,那么将这
137
- # 些查询字符串及其请求值按照字典序,从小到大排列,以 ’&’ 为分隔符,按参数的字典序添加到
138
- # CanonicalizedResource 中。此时的 CanonicalizedResource 例子:
139
- # /BucketName/ObjectName?acl&response-content-type=ContentType & uploadId =UploadId
140
- def canonicalized_resource()
141
- return @path unless @bucket
142
- return "/#{@bucket.name}#{@path}" if @queries.count == 0
143
-
144
- array = @queries.keys.sort.map do |k|
145
- if @queries[k] then "#{k}=#{@queries[k]}" else "#{k}" end
146
- end
147
-
148
- "/#{@bucket.name}#{@path}?#{array.sort.join('&')}"
149
- end
150
-
151
- end
152
-
153
- end
154
- end