aliyun-oss-sdk 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # Aliyun OSS SDK
2
2
 
3
- [![Build Status](https://travis-ci.org/zlx/aliyun-oss-sdk.svg)](https://travis-ci.org/zlx/aliyun-oss-sdk)
4
- [![Code Climate](https://codeclimate.com/github/zlx/aliyun-oss-sdk/badges/gpa.svg)](https://codeclimate.com/github/zlx/aliyun-oss-sdk)
5
- [![Coverage Status](https://coveralls.io/repos/zlx/aliyun-oss-sdk/badge.svg?branch=master&service=github)](https://coveralls.io/github/zlx/aliyun-oss-sdk?branch=master)
3
+ [![Build Status](https://travis-ci.org/zlx/aliyun-oss-sdk.svg?branch=develop)](https://travis-ci.org/zlx/aliyun-oss-sdk)
4
+ [![Code Climate](https://codeclimate.com/repos/56349060695680028b00b4a5/badges/fccd40948ea96a4eb507/gpa.svg)](https://codeclimate.com/repos/56349060695680028b00b4a5/feed)
5
+ [![Coverage Status](https://coveralls.io/repos/zlx/aliyun-oss-sdk/badge.svg?branch=develop&service=github)](https://coveralls.io/github/zlx/aliyun-oss-sdk?branch=develop)
6
6
 
7
7
  -----
8
8
 
9
9
 
10
- It provide One-to-one Ruby interface for Aliyun OSS Restful API. I try to keep things natural and reasonable, but there are always some places are leaky, welcome to give me advice and modification. Enjoy it!
10
+ It is a full-featured Ruby Library for Aliyun OSS API. We provide two ways to help you use the API: Function based and Object based. Besides, We try to keep things natural and reasonable, but there are always some leaky, welcome to give us advice and modification. Enjoy it!
11
11
 
12
12
 
13
13
 
@@ -25,11 +25,47 @@ And run:
25
25
 
26
26
  bundle install
27
27
 
28
+ ## Document
29
+
30
+ Here is original Restful API, It has the most detailed and authoritative explanation for every API.
31
+
32
+ + [https://docs.aliyun.com/#/pub/oss/api-reference/overview](https://docs.aliyun.com/#/pub/oss/api-reference/overview)
33
+
34
+ Here is thr RDoc Document for this Library, use to find mostly usage for methods.
35
+
36
+ + [RDoc Document](http://www.rubydoc.info/gems/aliyun-oss-sdk/0.1.1)
37
+
38
+
39
+ Here are some more guides for help you. Welcome to advice.
40
+
41
+ ### Function Based
42
+
43
+ + [Installation](./wiki/installation.md)
44
+ + [Getting Started](./wiki/get_start.md)
45
+ + [Bucket](./wiki/bucket.md)
46
+ + [Object](./wiki/object.md)
47
+ + [Multipart Upload](./wiki/multipart.md)
48
+ + [CORS](./wiki/cors.md)
49
+ + [LifeCycle](./wiki/lifecycle.md)
50
+ + [Error](./wiki/error.md)
51
+
52
+ ### Object Based
53
+
54
+ + [Installation](./wiki/object_based/installation.md)
55
+ + [Getting Started](./wiki/object_based/get_start.md)
56
+ + [Bucket](./wiki/object_based/bucket.md)
57
+ + [Object](./wiki/object_based/object.md)
58
+ + [Multipart Upload](./wiki/object_based/multipart.md)
59
+ + [CORS](./wiki/object_based/cors.md)
60
+ + [LifeCycle](./wiki/object_based/lifecycle.md)
61
+ + [Error](./wiki/error.md)
28
62
 
29
63
  ## Usage
30
64
 
31
65
  ### Quick Start
32
66
 
67
+ #### Function Based
68
+
33
69
  require 'aliyun/oss'
34
70
 
35
71
  # ACCESS_KEY/SECRET_KEY is your access credentials
@@ -40,18 +76,46 @@ And run:
40
76
  client = Aliyun::OSS::Client.new('ACCESS_KEY', 'SECRET_KEY', host: 'oss-cn-hangzhou.aliyuncs.com', bucket: 'oss-sdk-dev-hangzhou')
41
77
 
42
78
 
43
- # Upload objects
79
+ # Upload object
44
80
  client.bucket_create_object('image.png', File.new('path/to/image.png'), { 'Content-Type' => 'image/png' })
45
81
 
46
82
  # Get Object
47
83
  client.bucket_get_object('image.png')
48
84
 
49
85
 
50
-
51
86
  # Get all objects in this bucket
52
87
  # use prefix,marker,delimiter, max-keys to filter results
53
88
  client.bucket_list_objects()
89
+
90
+ #### Object Based
91
+
92
+ require 'aliyun/oss'
54
93
 
94
+ # ACCESS_KEY/SECRET_KEY is your access credentials
95
+ # host: your bucket's data center host, eg: oss-cn-hangzhou.aliyuncs.com
96
+ # Details: https://docs.aliyun.com/#/pub/oss/product-documentation/domain-region#menu2
97
+ # bucket: your bucket name
98
+
99
+ client = Aliyun::OSS::Client.new('ACCESS_KEY', 'SECRET_KEY', host: 'oss-cn-hangzhou.aliyuncs.com', bucket: 'oss-sdk-dev-hangzhou')
100
+
101
+
102
+ # Upload object
103
+ client.bucket_objects.create('image.png', File.new('path/to/image.png'), { 'Content-Type' => 'image/png' })
104
+
105
+ # Get Object
106
+ client.bucket_objects.get('image.png')
107
+
108
+ # Get all objects in this bucket
109
+ # use prefix,marker,delimiter, max-keys to filter results
110
+ client.bucket_objects.list()
111
+
112
+ #### Objects #####
113
+ buckets = client.buckets
114
+ bucket_objects = client.bucket_objects
115
+ bucket_multiparts = client.bucket_multiparts
116
+ bucket = client.buckets.list.first || Aliyun::Oss::Struct::Bucket.new(name: bucket_name, client: client)
117
+ multipart = client.bucket_multiparts.list.first || Aliyun::Oss::Struct::Multipart.new(upload_id: upload_id, key: object_key, client: client)
118
+ bucket_object = client.bucket_objects.list.first || Aliyun::Oss::Struct::Object.new(key: object_key, client: client)
55
119
 
56
120
  ### Share your files
57
121
 
@@ -78,151 +142,73 @@ With Post Form, we need Post Policy to restrict permissions, here we provide two
78
142
  client.get_policy_signature(SECRET_KEY, policy)
79
143
 
80
144
 
81
- ### Full API
82
-
83
-
84
- ###### Bucket #####
85
-
86
- # Get all buckets information
87
- client.list_buckets
88
-
89
- # Create new buckets
90
- client.bucket_create('oss-sdk-dev-beijing-no1', 'oss-cn-beijing', 'public-read')
91
-
92
- # Delete bucket
93
- client.bucket_delete(name)
94
-
95
- # Get all objects in this bucket
96
- # use prefix,marker,delimiter, max-keys to filter results
97
- client.bucket_list_objects()
98
-
99
-
100
- #### Get information of this bucket ####
101
-
102
- client.bucket_get_acl
103
- client.bucket_get_cors
104
- client.bucket_get_lifecycle
105
- client.bucket_get_location
106
- client.bucket_get_logging
107
- client.bucket_get_referer
108
- client.bucket_get_website
109
-
110
-
111
- ##### Set the bucket properties ####
112
-
113
- # set cors for bucket
114
- rule = Aliyun::Oss::Struct::Cors.new({ allowed_methods: ['get'], allowed_origins: ['*'] })
115
- client.bucket_enable_cors([rule])
116
- client.bucket_disable_cors # Disable and remove existing cors
117
-
118
- # Set lifecycle for bucket
119
- rule1 = Aliyun::Oss::Struct::LifeCycle.new({ prefix: 'logs-prod-', days: 7, enable: true })
120
- rule2 = Aliyun::Oss::Struct::LifeCycle.new({ prefix: 'logs-dev', date: Time.now + 24*60*60, enable: true })
121
- client.bucket_enable_lifecycle([rule1, rule2])
122
- client.bucket_disable_lifecycle # Disable and remove existing lifecycle
123
-
124
- # Enable access logging for bucket
125
- client.bucket_enable_logging('logs-oss-sdk', 'logs-')
126
- client.bucket_disable_logging # Disable logging
127
-
128
- # Set bucket to static web sites hosted mode.
129
- client.bucket_enable_website('index.html', 'error.html')
130
- client.bucket_disable_website # Disable static web sites hosted mode
131
-
132
- # Set Referer for this bucket
133
- client.bucket_set_referer(['http://www.aliyun.com'], false)
134
-
135
- # Set ACL for bucket
136
- # supported value: public-read-write | public-read | private
137
- client.bucket_set_acl('public-read')
138
-
139
-
140
- #### Object ####
141
-
142
- # Upload object to bucket
143
- client.bucket_create_object("image.png", File.new("path/to/image.png"), { 'Content-Type' => 'image/png' })
144
-
145
- # Copy object from other bucket
146
- client.bucket_copy_object('new_image.png', 'origin-bucket-name', 'origin.png', { 'x-oss-metadata-directive' => 'REPLACE' })
147
-
148
- # Get a Object
149
- client.bucket_get_object("image.png")
150
-
151
- # Get meta information of object
152
- client.bucket_get_meta_object("image.png")
153
-
154
- # Get object ACL
155
- client.bucket_get_object_acl("image.png")
156
-
157
- # Set object ACL
158
- client.bucket_set_object_acl("image.png", 'public-read-write')
159
-
160
- # upload object with append
161
- # it will create a Appendable object
162
- # https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject
163
- client.bucket_append_object("secret.zip", Bin Data, 0) # return the last position, 100203
164
- client.bucket_append_object("secret.zip", Bin Data, 100203)
165
-
166
- # Delete Object
167
- client.bucket_delete_object('secret.zip)
168
-
169
- # Delete Multiple objects
170
- client.bucket_delete_objects(['secret.zip', 'image.png'], true)
171
-
172
-
173
-
174
- #### Multipart Upload ####
175
-
176
- # Init a Multipart Upload event
177
- client.bucket_init_multipart("Exciting-Ruby.mp4", { 'Content-Type' => 'video/mp4' }) # return upload ID "98A6524428734723BE8F81D72B5295EE"
178
-
179
- # Upload files
180
- client.bucket_multipart_upload("Exciting-Ruby.mp4", 1, "98A6524428734723BE8F81D72B5295EE", file1) # return etag for use later
181
- client.bucket_multipart_upload("Exciting-Ruby.mp4", 2, "98A6524428734723BE8F81D72B5295EE", file2)
182
- client.bucket_multipart_upload("Exciting-Ruby.mp4", 3, "98A6524428734723BE8F81D72B5295EE", file3)
183
-
184
- # Copy from existing object
185
- client.bucket_multipart_copy_upload("Exciting-Ruby.mp4", 4, "98A6524428734723BE8F81D72B5295EE", source_bucket: 'original-bucket-name', source_key: 'original-file', range: 'bytes=0-10000')
186
-
187
- # List uploaded parts for a Multipart Upload event
188
- client.bucket_list_parts("sample_multipart.data", "98A6524428734723BE8F81D72B5295EE")
189
-
190
- # Complete a Multipart Upload event
191
- part1 = Aliyun::Oss::Struct::Part.new({ number: 1, etag: 'etag1' })
192
- part2 = Aliyun::Oss::Struct::Part.new({ number: 2, etag: 'etag2' })
193
- part3 = Aliyun::Oss::Struct::Part.new({ number: 3, etag: 'etag3' })
194
- client.bucket_complete_multipart("Exciting-Ruby.mp4", "98A6524428734723BE8F81D72B5295EE", [part1, part2, part3])
195
-
196
- # Abort a Multipart Upload event
197
- # abort will remove all uploaded parts
198
- # invoke a few time to confirm all parts are deleted for concurrency access
199
- client.bucket_abort_multipart("Exciting-Ruby.mp4", "9FB6F32C2DC24E04B813963B58E29E68")
200
-
201
-
202
-
203
-
204
- ## Document
205
-
206
- Here is original Restful API, It has the most detailed and authoritative explanation for every API.
207
-
208
- + [https://docs.aliyun.com/#/pub/oss/api-reference/overview](https://docs.aliyun.com/#/pub/oss/api-reference/overview)
209
-
210
- Here is thr Ruby Document for this Library, use to find more usage for methods.
211
-
212
- + [Ruby API Document](http://www.rubydoc.info/gems/aliyun-oss-sdk/0.0.1)
213
-
214
-
215
- Here are some more guides for help you. Welcome to advice.
216
-
217
- + [Installation](./wiki/installation.md)
218
- + [Getting Started](./wiki/get_start.md)
219
- + [Bucket](./wiki/bucket.md)
220
- + [Object](./wiki/object.md)
221
- + [Multipart Upload](./wiki/multipart.md)
222
- + [CORS](./wiki/cors.md)
223
- + [LifeCycle](./wiki/lifecycle.md)
224
- + [Error](./wiki/error.md)
225
-
145
+ ### API Mapping
146
+
147
+ We provide two type API: Function Based, Object Based. To help you find your needed methods, here list a mapping from Original Restful API to our methods.
148
+
149
+ Note:
150
+
151
+ + All Function Based API are instance methods of `Aliyun::Oss::Client`
152
+ + Object Based API belongs to some other class list below:
153
+
154
+ + buckets: `Aliyun::Oss::Client::BucketsService`
155
+ + bucket_objects: `Aliyun::Oss::Client::BucketObjectsService`
156
+ + bucket_multiparts: `Aliyun::Oss::Client::BucketMultipartsService`
157
+ + bucket: `Aliyun::Oss::Struct::Bucket`
158
+ + multipart: `Aliyun::Oss::Struct::Multipart`
159
+ + object: `Aliyun::Oss::Struct::Object`
160
+
161
+
162
+ | Restful API | Function Based | Object Based |
163
+ |---|---|
164
+ |[GetService (ListBucket)](https://docs.aliyun.com/#/pub/oss/api-reference/service&GetService) |bucket_list |buckets#list |
165
+ |[Put Bucket](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucket) |bucket_create | buckets#create|
166
+ |[Put Bucket Acl](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketACL) |bucket_set_acl | bucket#set_acl|
167
+ |[Put Bucket Logging](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketLogging)|bucket_enable_logging | bucket#enable_logging|
168
+ |[Put Bucket Website](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketWebsite) |bucket_enable_website | bucket#enable_website|
169
+ |[Put Bucket Referer](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketReferer) |bucket_set_referer | bucket#set_referer|
170
+ |[Put Bucket Lifecycle](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketLifecycle) | bucket_enable_lifecycle| bucket#enable_lifecycle|
171
+ |[Get Bucket (List Object)](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucket) | bucket_list_objects| bucket_objects#list|
172
+ |[Get Bucket ACL](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketAcl) | bucket_get_acl| bucket#acl!|
173
+ |[Get Bucket Location](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketLocation)| bucket_get_location| bucket#location!|
174
+ |[Get Bucket Logging](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketLogging) | bucket_get_logging| bucket#logging!|
175
+ |[Get Bucket Website](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketWebsite) | bucket_get_website| bucket#website!|
176
+ |[Get Bucket Referer](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketReferer) | bucket_get_referer| bucket#referer!|
177
+ |[Get Bucket Lifecycle](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketLifecycle) | bucket_get_lifecycle| bucket#lifecycle!|
178
+ |[Delete Bucket](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucket) | bucket_delete| buckets#delete|
179
+ |[Delete Bucket Logging](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucketLogging) | bucket_disable_logging| bucket#disable_logging|
180
+ |[Delete Bucket Website](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucketWebsite) | bucket_disable_website| bucket#disable_website|
181
+ |[Delete Bucket Lifecycle](https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucketLifecycle) | bucket_disable_lifecycle| bucket#disable_lifecycle|
182
+ |[Put Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject)| bucket_create_object| bucket_objects#create|
183
+ |[Copy Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&CopyObject) | bucket_copy_object| bucket_objects#copy|
184
+ |[Get Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&GetObject) | bucket_get_object| bucket_objects#get|
185
+ |[Append Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject)| bucket_append_object| bucket_objects#append|
186
+ |[Delete Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&DeleteObject)| bucket_delete_object| bucket_objects#delete|
187
+ |[Delete Multiple Objects](https://docs.aliyun.com/#/pub/oss/api-reference/object&DeleteMultipleObjects)| bucket_delete_objects| bucket_objects#delete_multiple|
188
+ |[Head Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject) | bucket_preflight| bucket#preflight, bucket#options|
189
+ |[Put Object ACL](https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObjectACL) | bucket_set_object_acl| object#set_acl|
190
+ |[Get Object ACL](https://docs.aliyun.com/#/pub/oss/api-reference/object&GetObjectACL) | bucket_get_object_acl| object#acl!|
191
+ |[Post Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&PostObject) | ...| ...|
192
+ |[Initiate Multipart Upload](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&InitiateMultipartUpload) | bucket_init_multipart| bucket_multiparts#init|
193
+ |[Upload Part](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&UploadPart) | bucket_multipart_upload| multipart#upload|
194
+ |[Upload Part Copy](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&UploadPartCopy) | bucket_multipart_copy_upload| multipart#copy|
195
+ |[Complete Multipart Upload](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&CompleteMultipartUpload) | bucket_complete_multipart| multipart#complete|
196
+ |[Abort Multipart Upload](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&AbortMultipartUpload) | bucket_abort_multipart| multipart#abort|
197
+ |[List Multipart Uploads](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&ListMultipartUploads) | bucket_list_multiparts| bucket_multiparts#list|
198
+ |[List Parts](https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&ListParts) | bucket_list_parts| multipart#list_parts|
199
+ |[Put Bucket cors](https://docs.aliyun.com/#/pub/oss/api-reference/cors&PutBucketcors) | bucket_enable_cors| bucket#enable_cors|
200
+ |[Get Bucket cors](https://docs.aliyun.com/#/pub/oss/api-reference/cors&GetBucketcors) | bucket_get_cors| bucket#cors!|
201
+ |[Delete Bucket cors](https://docs.aliyun.com/#/pub/oss/api-reference/cors&DeleteBucketcors) | bucket_disable_cors| bucket#disable_cors|
202
+ |[OPTIONS Object](https://docs.aliyun.com/#/pub/oss/api-reference/cors&OptionObject)| bucket_get_meta_object| object#meta!|
203
+
204
+
205
+ ## Test
206
+
207
+ We use minitest for test and rubocop for Syntax checker, If you want to make contribute to this library. Confirm below Command is success:
208
+
209
+ ```
210
+ bundle exec rake test
211
+ ```
226
212
 
227
213
 
228
214
  ## Authors && Contributors
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
 
12
12
  spec.summary = 'Aliyun OSS Ruby SDK'
13
13
  spec.description = 'Aliyun OSS Ruby SDK'
14
- spec.homepage = 'http://github.com/zlx/ruby-oss-sdk'
14
+ spec.homepage = 'https://github.com/zlx/aliyun-oss-sdk'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
17
  spec.bindir = 'exe'
@@ -25,7 +25,6 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'rake'
26
26
  spec.add_development_dependency 'minitest'
27
27
  spec.add_development_dependency 'mocha'
28
- spec.add_development_dependency 'pry-byebug'
29
28
  spec.add_development_dependency 'webmock'
30
29
  spec.add_development_dependency 'timecop'
31
30
  spec.add_development_dependency 'rubocop'
@@ -0,0 +1,184 @@
1
+ module Aliyun
2
+ module Oss
3
+ module Api
4
+ module BucketMultiparts
5
+ # Initialize a Multipart Upload event, before using Multipart Upload mode to transmit data, we has to call the interface to notify the OSS initialize a Multipart Upload events.
6
+ #
7
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&InitiateMultipartUpload Initiate Multipart Upload
8
+ #
9
+ # @param key [String] object name
10
+ # @param headers [Hash] headers
11
+ # @option headers [String] :Content-Type ('application/x-www-form-urlencoded') Specify Content-Type for the object
12
+ # @option headers [String] :Cache-Control Specify the caching behavior when download from browser, ref https://www.ietf.org/rfc/rfc2616.txt?spm=5176.730001.3.128.Y5W4bu&file=rfc2616.txt RFC2616}
13
+ # @option headers [String] :Content-Disposition Specify the name when download, ref https://www.ietf.org/rfc/rfc2616.txt?spm=5176.730001.3.128.Y5W4bu&file=rfc2616.txt RFC2616}
14
+ # @option headers [String] :Content-Encoding Specify the content encoding when download, ref https://www.ietf.org/rfc/rfc2616.txt?spm=5176.730001.3.128.Y5W4bu&file=rfc2616.txt RFC2616}
15
+ # @option headers [Integer] :Expires Specify the expiration time (milliseconds)
16
+ # @option headers [String] :x-oss-server-side-encryption Specify the oss server-side encryption algorithm when the object was created. supported value: 'AES256'#
17
+ #
18
+ # @return [Response]
19
+ def bucket_init_multipart(key, headers = {})
20
+ Utils.stringify_keys!(headers)
21
+ query = { 'uploads' => true }
22
+ http.post("/#{key}", query: query, headers: headers, bucket: bucket, key: key)
23
+ end
24
+
25
+ # Upload object in part.
26
+ #
27
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&UploadPart Upload Part
28
+ #
29
+ # @param key [String] object name
30
+ # @param number [Integer] the part number, Range in 1~10000.
31
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
32
+ # @param file [File, bin data] the upload data
33
+ #
34
+ # @raise [RequestError]
35
+ # @raise [MultipartPartNumberEmptyError]
36
+ # @raise [MultipartUploadIdEmptyError]
37
+ #
38
+ # @return [Response]
39
+ def bucket_multipart_upload(upload_id, key, number, file)
40
+ fail MultipartPartNumberEmptyError if number.nil?
41
+ fail MultipartUploadIdEmptyError if upload_id.nil? || upload_id.empty?
42
+
43
+ query = { 'partNumber' => number.to_s, 'uploadId' => upload_id }
44
+
45
+ http.put("/#{key}", query: query, body: Utils.to_data(file), bucket: bucket, key: key)
46
+ end
47
+
48
+ # Upload a Part from an existing Object Copy data.
49
+ #
50
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&UploadPartCopy Upload Part Copy
51
+ #
52
+ # @param key [String] object name
53
+ # @param number [Integer] the part number, Range in 1~10000.
54
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
55
+ # @param options [Hash] options
56
+ # @option options [String] :source_bucket the source bucket name
57
+ # @option options [String] :source_key the source object name
58
+ # @option options [String] :range the Range bytes, not set means the whole object, eg: bytes=100-6291756
59
+ # @option options [String] :x-oss-copy-source-if-match If the specified ETag match the source object ETag, normal transfer and return 200; Otherwise return 412(precondition)
60
+ # @option options [String] :x-oss-copy-source-if-none-match If the specified ETag not match the source object ETag, normal transfer and return 200; Otherwise return 304(Not Modified)
61
+ # @option options [String] :x-oss-copy-source-if-unmodified-since If the specified time is equal to or later than the source object last modification time, normal transfer ans return 200; Otherwise returns 412(precondition)
62
+ # @option options [String] :x-oss-copy-source-if-modified-since If the specified time is earlier than the source object last modification time, normal transfer ans return 200; Otherwise returns 304(not modified)
63
+ #
64
+ # @raise [RequestError]
65
+ # @raise [MultipartSourceBucketEmptyError]
66
+ # @raise [MultipartSourceKeyEmptyError]
67
+ #
68
+ # @return [Response]
69
+ def bucket_multipart_copy_upload(upload_id, key, number, options = {})
70
+ Utils.stringify_keys!(options)
71
+ source_bucket = options.delete('source_bucket').to_s
72
+ source_key = options.delete('source_key').to_s
73
+ range = options.delete('range')
74
+
75
+ fail MultipartSourceBucketEmptyError if source_bucket.empty?
76
+ fail MultipartSourceKeyEmptyError if source_key.empty?
77
+
78
+ query = { 'partNumber' => number, 'uploadId' => upload_id }
79
+ headers = copy_upload_headers(source_bucket, source_key, range, options)
80
+
81
+ http.put("/#{key}", query: query, headers: headers, bucket: bucket, key: key)
82
+ end
83
+
84
+ # Complete a Multipart Upload event.
85
+ #
86
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&CompleteMultipartUpload Complete Multipart Upload
87
+ #
88
+ # @param key [String] object name
89
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
90
+ # @param parts [Array<Aliyun::Oss::Multipart:Part>] parts
91
+ #
92
+ # @raise [RequestError]
93
+ # @raise [MultipartPartsEmptyError]
94
+ # @raise [MultipartUploadIdEmptyError]
95
+ #
96
+ # @return [Response]
97
+ def bucket_complete_multipart(upload_id, key, parts = [])
98
+ fail MultipartPartsEmptyError if parts.nil? || parts.empty?
99
+ fail MultipartUploadIdEmptyError if upload_id.nil?
100
+
101
+ query = { 'uploadId' => upload_id }
102
+
103
+ body = XmlGenerator.generate_complete_multipart_xml(parts)
104
+
105
+ http.post("/#{key}", query: query, body: body, bucket: bucket, key: key)
106
+ end
107
+
108
+ # Abort a Multipart Upload event
109
+ #
110
+ # @note After abort the Multipart Upload, the Uploaded data will be deleted
111
+ # @note When abort a Multipart Upload event, if there are still part upload belonging to this event, then theree parts will not be removed. So if there is a concurrent access, in order to release the space on the OSS completely, you need to call #bucket_abort_multipart a few times.
112
+ #
113
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&AbortMultipartUpload Abort Multipart Upload
114
+ #
115
+ # @param key [String] the object name
116
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
117
+ #
118
+ # @raise [RequestError]
119
+ #
120
+ # @return [Response]
121
+ def bucket_abort_multipart(upload_id, key)
122
+ query = { 'uploadId' => upload_id }
123
+ http.delete("/#{key}", query: query, bucket: bucket, key: key)
124
+ end
125
+
126
+ # List existing opened Multipart Upload event.
127
+ #
128
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&ListMultipartUploads List Multipart Uploads
129
+ #
130
+ # @param options [Hash] options
131
+ # @option options [String] :prefix Filter objects with prefix
132
+ # @option options [String] :delimiter Used to group objects with delimiter
133
+ # @option options [Integer] :max-uploads (1000) Limit number of Multipart Upload events, the maxinum should <= 1000
134
+ # @option options [String] :encoding-type Encoding type used for unsupported character
135
+ # @option options [String] :key-marker with upload-id-marker used to specify the result range.
136
+ # @option options [String] :upload-id-marker with key-marker used to specify the result range.
137
+ #
138
+ # @return [Response]
139
+ def bucket_list_multiparts(options = {})
140
+ Utils.stringify_keys!(options)
141
+ accepted_keys = ['prefix', 'key-marker', 'upload-id-marker', 'max-uploads', 'delimiter', 'encoding-type']
142
+
143
+ query = Utils.hash_slice(options, *accepted_keys)
144
+ .merge('uploads' => true)
145
+
146
+ http.get('/', query: query, bucket: bucket)
147
+ end
148
+
149
+ # List uploaded parts for Multipart Upload event
150
+ #
151
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&ListParts List Parts
152
+ #
153
+ # @param key [String] the object name
154
+ # @param upload_id [Integer] the upload ID return by #bucket_init_multipart
155
+ # @param options [Hash] options
156
+ # @option options [Integer] :max-parts (1000) Limit number of parts, the maxinum should <= 1000
157
+ # @option options [Integer] :part-number-marker Specify the start part, return parts which number large than the specified value
158
+ # @option options [String] :encoding-type Encoding type used for unsupported character in xml 1.0
159
+ #
160
+ # @return [Response]
161
+ def bucket_list_parts(upload_id, key, options = {})
162
+ Utils.stringify_keys!(options)
163
+ accepted_keys = ['max-parts', 'part-number-marker', 'encoding-type']
164
+
165
+ query = Utils.hash_slice(options, *accepted_keys).merge('uploadId' => upload_id)
166
+
167
+ http.get("/#{key}", query: query, bucket: bucket, key: key)
168
+ end
169
+
170
+ private
171
+
172
+ def copy_upload_headers(source_bucket, source_key, range, options)
173
+ copy_source = "/#{source_bucket}/#{source_key}"
174
+
175
+ headers = {}
176
+ headers.merge!('x-oss-copy-source' => copy_source)
177
+ headers.merge!('x-oss-copy-source-range' => range) if range
178
+ headers.merge!(options)
179
+ headers
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end