aliyun-oss-sdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 25f9ea0e6c34c0a6d15ff9c7f1c5b7063eab4c74
4
+ data.tar.gz: 3ff1e1a73d6b74bbaec4ff7e23179197197978ae
5
+ SHA512:
6
+ metadata.gz: 12ca936fc5538dac82a12a6dd1ec3057f12d31bf0bd163931e6bc98b0215070abbd76c6191d8de1ae4e8d346249217c7a7ebad8948aed0a871bb5471117e3568
7
+ data.tar.gz: 5917b901eed5f2b8182719474418b212382bfdd678c93a95a29ef3ea33e3aa4d169715f153648281837edd02cb84a5a83f36cfb81b01b6f518f7c890adf6c6f1
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://ruby.taobao.org'
2
+
3
+ # Specify your gem's dependencies in ruby-oss-sdk.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,195 @@
1
+ # Aliyun OSS SDK
2
+
3
+ [![Coverage Status](https://coveralls.io/repos/zlx/ruby-oss-sdk/badge.svg?branch=master&service=bitbucket)](https://coveralls.io/bitbucket/zlx/ruby-oss-sdk?branch=master)
4
+
5
+ -----
6
+
7
+
8
+ 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. Thank you!
9
+
10
+
11
+ ## Document
12
+
13
+ + [ALiyun OSS API](https://docs.aliyun.com/#/pub/oss/api-reference/overview)
14
+ + [Ruby Document]()
15
+
16
+
17
+ ## Usage
18
+
19
+ ### Quick Start
20
+
21
+ require 'aliyun/oss'
22
+
23
+ # ACCESS_KEY/SECRET_KEY is your access credentials, Aliyun provide three ways, read detail at https://docs.aliyun.com/#/pub/oss/product-documentation/acl&RESTAuthentication
24
+ # host: your bucket's data center host, eg: oss-cn-hangzhou.aliyuncs.com, visit https://docs.aliyun.com/#/pub/oss/product-documentation/domain-region#menu2 get full list
25
+ # bucket: your bucket name
26
+
27
+ client = Aliyun::OSS::Client.new('ACCESS_KEY', 'SECRET_KEY', host: 'oss-cn-hangzhou.aliyuncs.com', bucket: 'oss-sdk-dev-hangzhou')
28
+
29
+ # Get all objects in this bucket
30
+ # use prefix,marker,delimiter, max-keys to filter results
31
+ client.bucket_list_objects()
32
+
33
+ # Upload objects
34
+ client.bucket_create_object('image.png', File.new('path/to/image.png'), { 'Content-Type' => 'image/png' })
35
+
36
+ # Get Object
37
+ client.bucket_get_object('image.png')
38
+
39
+
40
+ ### Share your files
41
+
42
+ Sometimes, you want to share some file in your private bucket with your friends , but you donot want to share your AccessKey, thus, Aliyun provide alternative way: [Put signature in URL](https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-url)
43
+
44
+ We provide a method to calculate signature for you:
45
+
46
+ # Return Singature string
47
+ Aliyun::Oss::Authorization.get_temporary_signature('SECRET_KEY', Time.now.to_i + 60*60, verb: 'GET', bucket: 'bucket-name', key: 'object-name')
48
+
49
+
50
+ ### Directly POST file to Aliyun OSS
51
+
52
+ Sometime we may allow user directly upload image or file to Aliyun to improve the upload speed. thus you may need POST form: [Post Object](https://docs.aliyun.com/#/pub/oss/api-reference/object&PostObject)
53
+
54
+ With Post Form, we need Post Policy to restrict permissions, here we provide two methods that you may interesting:
55
+
56
+ # policy your policy in hash
57
+ # Return base64 string which can used to fill your form field: policy
58
+ client.get_base64_policy(policy)
59
+
60
+ # Get Signature for policy
61
+ # Return Signature with policy, can used to fill your form field: Signature
62
+ client.get_policy_signature(SECRET_KEY, policy)
63
+
64
+
65
+ ### Full API
66
+
67
+
68
+ ###### Bucket #####
69
+
70
+ # Get all buckets information
71
+ client.list_buckets
72
+
73
+ # Create new buckets
74
+ client.bucket_create('oss-sdk-dev-beijing-no1', 'oss-cn-beijing', 'public-read')
75
+
76
+ # Delete bucket
77
+ client.bucket_delete(name)
78
+
79
+ # Get all objects in this bucket
80
+ # use prefix,marker,delimiter, max-keys to filter results
81
+ client.bucket_list_objects()
82
+
83
+
84
+ #### Get information of this bucket ####
85
+
86
+ client.bucket_get_acl
87
+ client.bucket_get_cors
88
+ client.bucket_get_lifecycle
89
+ client.bucket_get_location
90
+ client.bucket_get_logging
91
+ client.bucket_get_referer
92
+ client.bucket_get_website
93
+
94
+
95
+ ##### Set the bucket properties ####
96
+
97
+ # set cors for bucket
98
+ rule = Aliyun::Oss::Rule::Cors.new({ allowed_methods: ['get'], allowed_origins: ['*'] })
99
+ client.bucket_enable_cors([rule])
100
+ client.bucket_disable_cors # Disable and remove existing cors
101
+
102
+ # Set lifecycle for bucket
103
+ rule1 = Aliyun::Oss::Rule::LifeCycle.new({ prefix: 'logs-prod-', days: 7, enable: true })
104
+ rule2 = Aliyun::Oss::Rule::LifeCycle.new({ prefix: 'logs-dev', date: Time.now + 24*60*60, enable: true })
105
+ client.bucket_enable_lifecycle([rule1, rule2])
106
+ client.bucket_disable_lifecycle # Disable and remove existing lifecycle
107
+
108
+ # Enable access logging for bucket
109
+ client.bucket_enable_logging('logs-oss-sdk', 'logs-')
110
+ client.bucket_disable_logging # Disable logging
111
+
112
+ # Set bucket to static web sites hosted mode.
113
+ client.bucket_enable_website('index.html', 'error.html')
114
+ client.bucket_disable_website # Disable static web sites hosted mode
115
+
116
+ # Set Referer for this bucket
117
+ client.bucket_set_referer(['http://www.aliyun.com'], false)
118
+
119
+ # Set ACL for bucket
120
+ # supported value: public-read-write | public-read | private
121
+ client.bucket_set_acl('public-read')
122
+
123
+
124
+ #### Object ####
125
+
126
+ # Upload object to bucket
127
+ client.bucket_create_object("image.png", File.new("path/to/image.png"), { 'Content-Type' => 'image/png' })
128
+
129
+ # Copy object from other bucket
130
+ client.bucket_copy_object('new_image.png', 'origin-bucket-name', 'origin.png', { 'x-oss-metadata-directive' => 'REPLACE' })
131
+
132
+ # Get a Object
133
+ client.bucket_get_object("image.png")
134
+
135
+ # Get meta information of object
136
+ client.bucket_get_meta_object("image.png")
137
+
138
+ # Get object ACL
139
+ client.bucket_get_object_acl("image.png")
140
+
141
+ # Set object ACL
142
+ client.bucket_set_object_acl("image.png", 'public-read-write')
143
+
144
+ # upload object with append
145
+ # it will create a Appendable object
146
+ # https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject
147
+ client.bucket_append_object("secret.zip", Bin Data, 0) # return the last position, 100203
148
+ client.bucket_append_object("secret.zip", Bin Data, 100203)
149
+
150
+ # Delete Object
151
+ client.bucket_delete_object('secret.zip)
152
+
153
+ # Delete Multiple objects
154
+ client.bucket_delete_objects(['secret.zip', 'image.png'], true)
155
+
156
+
157
+
158
+ #### Multipart Upload ####
159
+
160
+ # Init a Multipart Upload event
161
+ client.bucket_init_multipart("Exciting-Ruby.mp4", { 'Content-Type' => 'video/mp4' }) # return upload ID "98A6524428734723BE8F81D72B5295EE"
162
+
163
+ # Upload files
164
+ client.bucket_multipart_upload("Exciting-Ruby.mp4", 1, "98A6524428734723BE8F81D72B5295EE", file1) # return etag for use later
165
+ client.bucket_multipart_upload("Exciting-Ruby.mp4", 2, "98A6524428734723BE8F81D72B5295EE", file2)
166
+ client.bucket_multipart_upload("Exciting-Ruby.mp4", 3, "98A6524428734723BE8F81D72B5295EE", file3)
167
+
168
+ # Copy from existing object
169
+ client.bucket_multipart_copy_upload("Exciting-Ruby.mp4", 4, "98A6524428734723BE8F81D72B5295EE", source_bucket: 'original-bucket-name', source_key: 'original-file', range: 'bytes=0-10000')
170
+
171
+ # List uploaded parts for a Multipart Upload event
172
+ client.bucket_list_parts("sample_multipart.data", "98A6524428734723BE8F81D72B5295EE")
173
+
174
+ # Complete a Multipart Upload event
175
+ part1 = Aliyun::Oss::Multipart::Part.new({ number: 1, etag: 'etag1' })
176
+ part2 = Aliyun::Oss::Multipart::Part.new({ number: 2, etag: 'etag2' })
177
+ part3 = Aliyun::Oss::Multipart::Part.new({ number: 3, etag: 'etag3' })
178
+ client.bucket_complete_multipart("Exciting-Ruby.mp4", "98A6524428734723BE8F81D72B5295EE", [part1, part2, part3])
179
+
180
+ # Abort a Multipart Upload event
181
+ # abort will remove all uploaded parts
182
+ # invoke a few time to confirm all parts are deleted for concurrency access
183
+ client.bucket_abort_multipart("Exciting-Ruby.mp4", "9FB6F32C2DC24E04B813963B58E29E68")
184
+
185
+
186
+
187
+
188
+ ## Authors && Contributors
189
+
190
+ - [Newell Zhu](https://github.com/zlx_star)
191
+
192
+
193
+ ## License
194
+
195
+ licensed under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task default: :test
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aliyun/oss/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'aliyun-oss-sdk'
8
+ spec.version = Aliyun::Oss::VERSION
9
+ spec.authors = ['Newell Zhu']
10
+ spec.email = ['zlx.star@gmail.com']
11
+
12
+ spec.summary = 'Aliyun OSS Ruby SDK'
13
+ spec.description = 'Aliyun OSS Ruby SDK'
14
+ spec.homepage = 'http://github.com/aliyun/ruby-oss-sdk'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = 'exe'
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'httparty'
22
+ spec.add_dependency 'gyoku'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.10'
25
+ spec.add_development_dependency 'rake', '~> 10.0'
26
+ spec.add_development_dependency 'minitest'
27
+ spec.add_development_dependency 'mocha'
28
+ spec.add_development_dependency 'pry-byebug'
29
+ spec.add_development_dependency 'webmock'
30
+ spec.add_development_dependency 'timecop'
31
+ spec.add_development_dependency 'simplecov'
32
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'aliyun/oss'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/lib/aliyun/oss.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'aliyun/oss/version'
2
+
3
+ module Aliyun
4
+ module Oss
5
+ autoload :Utils, 'aliyun/oss/utils'
6
+ autoload :Client, 'aliyun/oss/client'
7
+ autoload :Http, 'aliyun/oss/http'
8
+ autoload :XmlBuilder, 'aliyun/oss/xml_builder'
9
+ autoload :Authorization, 'aliyun/oss/authorization'
10
+
11
+ module Rule
12
+ autoload :LifeCycle, 'aliyun/oss/rule/lifecycle'
13
+ autoload :Cors, 'aliyun/oss/rule/cors'
14
+ end
15
+
16
+ module Multipart
17
+ autoload :Part, 'aliyun/oss/multipart/part'
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,117 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'digest'
4
+ require 'json'
5
+
6
+ module Aliyun
7
+ module Oss
8
+ class Authorization
9
+ PROVIDER = 'OSS'
10
+
11
+ # Get temporary Signature
12
+ #
13
+ # @see {https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-url Tempoorary Signature}
14
+ #
15
+ # @param secret_key [String] Secret Key
16
+ # @param expires [Integer] the number of seconds since January 1, 1970 UTC. used to specified expired time
17
+ # @param [Hash] options other options
18
+ # @option options [String] :key the object name
19
+ # @option options [String] :bucket bucket name
20
+ # @option options [String] :verb, Request Method
21
+ # @option options [Hash] :query Query Params
22
+ # @option options [Hash] :headers Headers Params
23
+ #
24
+ # @return [String]
25
+ def self.get_temporary_signature(secret_key, expire_time, options = {})
26
+ content_string = concat_content_string(options[:verb], expire_time, options)
27
+ URI.escape(signature(secret_key, content_string).strip)
28
+ end
29
+
30
+ # Get base64 encoded string, used to fill policy field
31
+ #
32
+ # @see {https://docs.aliyun.com/#/pub/oss/api-reference/object&PostObject Post Object}
33
+ #
34
+ # @param secret_key [String] Secret Key
35
+ # @param policy [Hash] Policy {https://docs.aliyun.com/#/pub/oss/api-reference/object&PostObject#menu7 Detail}
36
+ #
37
+ # @return [String]
38
+ def self.get_base64_policy(policy)
39
+ Base64.encode64(JSON.generate(policy).force_encoding('utf-8')).delete("\n")
40
+ end
41
+
42
+ # Get Signature for policy
43
+ #
44
+ # @see {https://docs.aliyun.com/#/pub/oss/api-reference/object&PostObject}
45
+ #
46
+ # @param secret_key [String] Secret Key
47
+ # @param policy [Hash] Policy {https://docs.aliyun.com/#/pub/oss/api-reference/object&PostObject#menu7 Detail}
48
+ #
49
+ # @return [String]
50
+ def self.get_policy_signature(secret_key, policy)
51
+ signature(secret_key, get_base64_policy(policy)).strip
52
+ end
53
+
54
+ # @private
55
+ #
56
+ # Get authorization key
57
+ #
58
+ # @see {https://docs.aliyun.com/#/pub/oss/api-reference/access-control&signature-header Authorization}
59
+ #
60
+ # @return [String] the authorization string
61
+ def self.get_authorization(access_key, secret_key, options = {})
62
+ content_string = concat_content_string(options[:verb], options[:date], options)
63
+ signature_string = signature(secret_key, content_string)
64
+ "#{PROVIDER} #{access_key}:#{signature_string.strip}"
65
+ end
66
+
67
+ private
68
+
69
+ def self.concat_content_string(verb, time, options = {})
70
+ headers = options.fetch(:headers, {})
71
+
72
+ cononicalized_oss_headers = get_cononicalized_oss_headers(headers)
73
+ cononicalized_resource = get_cononicalized_resource(*options.values_at(:bucket, :key, :query))
74
+
75
+ if cononicalized_oss_headers
76
+ [
77
+ verb.upcase,
78
+ headers['Content-MD5'],
79
+ headers['Content-Type'],
80
+ time,
81
+ cononicalized_oss_headers,
82
+ cononicalized_resource
83
+ ].join("\n")
84
+ else
85
+ [
86
+ verb.upcase,
87
+ headers['Content-MD5'],
88
+ headers['Content-Type'],
89
+ time,
90
+ cononicalized_resource
91
+ ].join("\n")
92
+ end
93
+ end
94
+
95
+ def self.signature(secret_key, content_string)
96
+ utf8_string = content_string.force_encoding('utf-8')
97
+ Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA1.new, secret_key, utf8_string))
98
+ end
99
+
100
+ def self.get_cononicalized_oss_headers(headers)
101
+ oss_headers = (headers || {}).select { |key, _| key.to_s.downcase.start_with?('x-oss-') }
102
+ return if oss_headers.empty?
103
+
104
+ oss_headers.keys.sort.map { |key| "#{key.downcase}:#{oss_headers[key]}" }.join("\n")
105
+ end
106
+
107
+ def self.get_cononicalized_resource(bucket, key, query)
108
+ cononicalized_resource = '/'
109
+ cononicalized_resource += "#{bucket}/" if bucket
110
+ cononicalized_resource += key if key
111
+ return cononicalized_resource if query.nil? || query.empty?
112
+
113
+ cononicalized_resource + '?' + query.keys.sort.map { |key| "#{key}=#{query[key]}" }.join('&')
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,635 @@
1
+ require 'base64'
2
+ require 'openssl'
3
+ require 'digest'
4
+ require 'httparty'
5
+
6
+ module Aliyun
7
+ module Oss
8
+ class Client
9
+ attr_reader :access_key, :secret_key, :bucket
10
+
11
+ # Initialize a object
12
+ #
13
+ # @example
14
+ # Aliyun::Oss::Client.new("ACCESS_KEY", "SECRET_KEY", host: "oss-cn-beijing.aliyuncs.com", bucket: 'oss-sdk-beijing')
15
+ #
16
+ # @param access_key [String] access_key obtained from aliyun
17
+ # @param secret_key [String] secret_key obtained from aliyun
18
+ # @option options [String] :host host for bucket's data center
19
+ # @option options [String] :bucket Bucket name
20
+ #
21
+ # @return [Client] the object
22
+ def initialize(access_key, secret_key, options = {})
23
+ @access_key = access_key
24
+ @secret_key = secret_key
25
+ @options = options
26
+ @bucket = options[:bucket]
27
+ end
28
+
29
+ # List buckets
30
+ #
31
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/service&GetService GetService (ListBucket
32
+ #
33
+ # @param options [Hash] options
34
+ # @option options [String] :prefix Filter buckets with prefix
35
+ # @option options [String] :marker Bucket name should after marker in alphabetical order
36
+ # @option options [Integer] :max-keys (100) Limit number of buckets, the maxinum should <= 1000
37
+ #
38
+ # @return [Object{buckets}]
39
+ def list_buckets(options = {})
40
+ query = Utils.hash_slice(options, 'prefix', 'marker', 'max-keys')
41
+ http.get('/', query: query)
42
+ end
43
+
44
+ # List objects in the bucket
45
+ #
46
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucket Get Bucket (List Object)
47
+ #
48
+ # @param options [Hash] options
49
+ # @option options [String] :prefix Filter objects with prefix
50
+ # @option options [String] :marker Result should after marker in alphabetical order
51
+ # @option options [Integer] :max-keys (100) Limit number of objects, the maxinum should <= 1000
52
+ # @option options [String] :delimiter Used to group objects with delimiter
53
+ # @option options [String] :encoding-type Encoding type used for unsupported character
54
+ #
55
+ # @return [Object{objects}]
56
+ def bucket_list_objects(options = {})
57
+ accepted_keys = ['prefix', 'marker', 'max-keys', 'delimiter', 'encoding-type']
58
+ query = Utils.hash_slice(options, *accepted_keys)
59
+ http.get('/', query: query, bucket: bucket)
60
+ end
61
+
62
+ # Create bucket
63
+ #
64
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucket Put Bucket
65
+ #
66
+ # @example
67
+ # oss.client.bucket_create('oss-sdk-dev-hangzhou-xxx')
68
+ #
69
+ # @param name [String] Specify bucket name
70
+ # @param location [String] Specify the bucket's data center location, can be one of below:
71
+ # oss-cn-hangzhou,oss-cn-qingdao,oss-cn-beijing,oss-cn-hongkong,
72
+ # oss-cn-shenzhen,oss-cn-shanghai,oss-us-west-1 ,oss-ap-southeast-1
73
+ # @param acl [String] Specify the bucket's access. (see #bucket_set_acl)
74
+ #
75
+ # @return [Response]
76
+ def bucket_create(name, location = 'oss-cn-hangzhou', acl = 'private')
77
+ query = { 'acl' => true }
78
+ headers = { 'x-oss-acl' => acl }
79
+
80
+ configuration = { 'CreateBucketConfiguration' => { 'LocationConstraint' => location } }
81
+ body = Utils.to_xml(configuration)
82
+
83
+ http.put('/', query: query, headers: headers, body: body, bucket: name, location: location)
84
+ end
85
+
86
+ # Delete bucket
87
+ #
88
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucket Delete Bucket
89
+ #
90
+ # @param name [String] bucket name want to delete
91
+ #
92
+ # @return [Response]
93
+ def bucket_delete(name)
94
+ http.delete('/', bucket: name)
95
+ end
96
+
97
+ # Used to modify the bucket access.
98
+ #
99
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketACL Put Bucket Acl
100
+ #
101
+ # @param acl [String] supported value: public-read-write | public-read | private
102
+ def bucket_set_acl(acl)
103
+ query = { 'acl' => true }
104
+ headers = { 'x-oss-acl' => acl }
105
+ http.put('/', query: query, headers: headers, bucket: bucket)
106
+ end
107
+
108
+ # Used to enable access logging.
109
+ #
110
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketLogging Put Bucket Logging
111
+ #
112
+ # @param target_bucket [String] specifies the bucket where you want Aliyun OSS to store server access logs.
113
+ # @param target_prefix [String] this element lets you specify a prefix for the objects that the log files will be stored.
114
+ def bucket_enable_logging(target_bucket, target_prefix = nil)
115
+ query = { 'logging' => true }
116
+
117
+ logging = { 'TargetBucket' => target_bucket }
118
+ logging.merge!('TargetPrefix' => target_prefix) if target_prefix
119
+ body = Utils.to_xml('BucketLoggingStatus' => { 'LoggingEnabled' => logging })
120
+
121
+ http.put('/', query: query, body: body, bucket: bucket)
122
+ end
123
+
124
+ # Used to disable access logging.
125
+ #
126
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucketLogging Delete Bucket Logging
127
+ def bucket_disable_logging
128
+ query = { 'logging' => false }
129
+ http.delete('/', query: query, bucket: bucket)
130
+ end
131
+
132
+ # Used to enable static website hosted mode.
133
+ #
134
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketWebsite Put Bucket Website
135
+ #
136
+ # @param suffix [String] A suffix that is appended to a request that is for a directory on the website endpoint (e.g. if the suffix is index.html and you make a request to samplebucket/images/ the data that is returned will be for the object with the key name images/index.html) The suffix must not be empty and must not include a slash character.
137
+ # @param key [String] The object key name to use when a 4XX class error occurs
138
+ def bucket_enable_website(suffix, key = nil)
139
+ query = { 'website' => true }
140
+
141
+ website_configuration = { 'IndexDocument' => { 'Suffix' => suffix } }
142
+ website_configuration.merge!('ErrorDocument' => { 'Key' => key }) if key
143
+ body = Utils.to_xml('WebsiteConfiguration' => website_configuration)
144
+
145
+ http.put('/', query: query, body: body, bucket: bucket)
146
+ end
147
+
148
+ # Used to disable website hostted mode.
149
+ #
150
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucketWebsite Delete Bucket Website
151
+ def bucket_disable_website
152
+ query = { 'website' => false }
153
+ http.delete('/', query: query, bucket: bucket)
154
+ end
155
+
156
+ # Used to set referer for bucket.
157
+ #
158
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketReferer Put Bucket Referer
159
+ #
160
+ # @param referers [Array<String>] white list for allowed referer.
161
+ # @param allowed_empty [Boolean] whether allow empty refer.
162
+ #
163
+ # @return [Response]
164
+ def bucket_set_referer(referers = [], allowed_empty = false)
165
+ query = { 'referer' => true }
166
+
167
+ referer_configuration = { 'RefererConfiguration' => { 'AllowEmptyReferer' => allowed_empty, 'RefererList' => { 'Referer' => referers } } }
168
+ body = Utils.to_xml(referer_configuration)
169
+
170
+ http.put('/', query: query, body: body, bucket: bucket)
171
+ end
172
+
173
+ # Used to enable and set lifecycle for bucket
174
+ #
175
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&PutBucketLifecycle Put Bucket Lifecycle
176
+ #
177
+ # @param rules [Array<Rule::LifeCycle>] rules for lifecycle
178
+ #
179
+ # @return [Response]
180
+ def bucket_enable_lifecycle(rules = [])
181
+ query = { 'lifecycle' => true }
182
+
183
+ body = Utils.to_xml('LifecycleConfiguration' => {
184
+ 'Rule' => rules.map(&:to_hash)
185
+ })
186
+
187
+ http.put('/', query: query, body: body, bucket: bucket)
188
+ end
189
+
190
+ # Used to disable lifecycle for bucket.
191
+ #
192
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&DeleteBucketLifecycle Delete Bucket Lifecycle
193
+ def bucket_disable_lifecycle
194
+ query = { 'lifecycle' => false }
195
+ http.delete('/', query: query, bucket: bucket)
196
+ end
197
+
198
+ # Used to enable CORS and set rules for bucket
199
+ #
200
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/cors&PutBucketcors Put Bucket cors
201
+ #
202
+ # @param rules [Array<Rule::Cors>] array of rule
203
+ #
204
+ # @return [Response]
205
+ def bucket_enable_cors(rules = [])
206
+ query = { 'cors' => true }
207
+
208
+ body = Utils.to_xml('CORSConfiguration' => {
209
+ 'CORSRule' => rules.map(&:to_hash)
210
+ })
211
+
212
+ http.put('/', query: query, body: body, bucket: bucket)
213
+ end
214
+
215
+ # Used to disable cors and clear rules for bucket
216
+ #
217
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/cors&DeleteBucketcors Delete Bucket cors
218
+ #
219
+ # @return [Response]
220
+ def bucket_disable_cors
221
+ query = { 'cors' => false }
222
+ http.delete('/', query: query, bucket: bucket)
223
+ end
224
+
225
+ # OPTIONS Object
226
+ #
227
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/cors&OptionObject OPTIONS Object
228
+ #
229
+ # @param origin [String] the requested source domain, denoting cross-domain request.
230
+ # @param request_method [String] the actual request method will be used.
231
+ # @param request_headers [Array<String>] the actual used headers except simple headers will be used.
232
+ # @param object_name [String] the object name will be visit.
233
+ #
234
+ # @return [Response]
235
+ def bucket_preflight(origin, request_method, request_headers = [], object_name = nil)
236
+ uri = object_name ? "/#{object_name}" : '/'
237
+
238
+ headers = { 'Origin' => origin, 'Access-Control-Request-Method' => request_method }
239
+ unless request_headers.empty?
240
+ headers.merge!('Access-Control-Request-Headers' => request_headers.join(','))
241
+ end
242
+
243
+ http.options(uri, headers: headers, bucket: bucket, key: object_name)
244
+ end
245
+
246
+ # Get ACL for bucket
247
+ #
248
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketAcl Get Bucket ACL
249
+ #
250
+ # @return [Response]
251
+ def bucket_get_acl
252
+ query = { 'acl' => true }
253
+ http.get('/', query: query, bucket: bucket)
254
+ end
255
+
256
+ # Get the location information of the Bucket's data center
257
+ #
258
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketLocation Get Bucket Location
259
+ #
260
+ # @return [Response]
261
+ def bucket_get_location
262
+ query = { 'location' => true }
263
+ http.get('/', query: query, bucket: bucket)
264
+ end
265
+
266
+ # Get the log configuration of Bucket
267
+ #
268
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketLogging Get Bucket Logging
269
+ #
270
+ # @return [Response]
271
+ def bucket_get_logging
272
+ query = { 'logging' => true }
273
+ http.get('/', query: query, bucket: bucket)
274
+ end
275
+
276
+ # Get the bucket state of static website hosting.
277
+ #
278
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketWebsite Get Bucket Website
279
+ #
280
+ # @return [Response]
281
+ def bucket_get_website
282
+ query = { 'website' => true }
283
+ http.get('/', query: query, bucket: bucket)
284
+ end
285
+
286
+ # Get the referer configuration of bucket
287
+ #
288
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketReferer Get Bucket Referer
289
+ #
290
+ # @return [Response]
291
+ def bucket_get_referer
292
+ query = { 'referer' => true }
293
+ http.get('/', query: query, bucket: bucket)
294
+ end
295
+
296
+ # Get the lifecycle configuration of bucket
297
+ #
298
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/bucket&GetBucketLifecycle Get Bucket Lifecycle
299
+ #
300
+ # @return [Response]
301
+ def bucket_get_lifecycle
302
+ query = { 'lifecycle' => true }
303
+ http.get('/', query: query, bucket: bucket)
304
+ end
305
+
306
+ # Get the CORS rules of bucket
307
+ #
308
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/cors&GetBucketcors Get Bucket cors
309
+ #
310
+ # @return [Response]
311
+ def bucket_get_cors
312
+ query = { 'cors' => true }
313
+ http.get('/', query: query, bucket: bucket)
314
+ end
315
+
316
+ # Upload file to bucket
317
+ #
318
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObject Put Object
319
+ #
320
+ # @param key [String] Specify object name
321
+ # @param file [File, Bin data] Specify need upload resource
322
+ # @param [Hash] headers Specify other options
323
+ # @option headers [String] :Content-Type ('application/x-www-form-urlencoded') Specify Content-Type for the object
324
+ # @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}
325
+ # @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}
326
+ # @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}
327
+ # @option headers [String] :Content-MD5 RFC 1864 according to the agreement of the message Content (not including head) are calculated MD5 value 128 bits number, the number is base64 encoding for the Content of a message - MD5 value.The legality of the examination of the request headers can be used for information (a message content is consistent with send).Although the request header is optional, OSS recommend that users use the end-to-end check request header.
328
+ # @option headers [Integer] :Expires Specify the expiration time (milliseconds)
329
+ # @option headers [String] :x-oss-server-side-encryption Specify the oss server-side encryption algorithm when the object was created. supported value: 'AES256'
330
+ # @option headers [String] :x-oss-object-acl Specify the oss access when the object was created. supported value: public-read-write | public-read | private
331
+ # @option headers [Hash] other options will insert into headers when upload, such as user meta headers, eg: headers with prefix: x-oss-meta-
332
+ #
333
+ # @return [Response]
334
+ def bucket_create_object(key, file, headers = {})
335
+ http.put("/#{key}", headers: headers, body: Utils.to_data(file), bucket: bucket, key: key)
336
+ end
337
+
338
+ # Copy an existing object in OSS into another object
339
+ #
340
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&CopyObject Copy Object
341
+ #
342
+ # @param key [String] the object name
343
+ # @param source_bucket [String] the source bucket name
344
+ # @param source_key [String] the source object name
345
+ # @param [Hash] headers
346
+ # @option options [String] :source_bucket the source bucket name
347
+ # @option options [String] :source_key the source object name
348
+ # @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)
349
+ # @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)
350
+ # @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)
351
+ # @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)
352
+ # @option options [String] :x-oss-metadata-directive ('COPY') supported value: COPY, REPLACE;
353
+ # @option options [String] :x-oss-server-side-encryption supported value: AES256
354
+ # @option options [String] :x-oss-object-acl supported value: public-read,private,public-read-write
355
+ #
356
+ # @return [Response]
357
+ def bucket_copy_object(key, source_bucket, source_key, headers = {})
358
+ fail('source_bucket must be not empty!') if source_bucket.nil? || source_bucket.empty?
359
+ fail('source_key must be not empty!') if source_key.nil? || source_key.empty?
360
+
361
+ headers.merge!('x-oss-copy-source' => "/#{source_bucket}/#{source_key}")
362
+
363
+ http.put("/#{key}", headers: headers, bucket: bucket, key: key)
364
+ end
365
+
366
+ # Append data to a object, will create Appendable object
367
+ #
368
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&AppendObject Append Object
369
+ #
370
+ # @param key [String] object name
371
+ # @param file [file, bin data] the data to append
372
+ # @param position [Integer] append to position of object
373
+ # @option headers (see #bucket_create_object)
374
+ #
375
+ def bucket_append_object(key, file, position = 0, headers = {})
376
+ query = { 'append' => true, 'position' => position }
377
+
378
+ body = Utils.to_data(file)
379
+
380
+ http.post("/#{key}", query: query, headers: headers, body: body, bucket: bucket, key: key)
381
+ end
382
+
383
+ # Get the object
384
+ #
385
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&GetObject Get Object
386
+ #
387
+ # @param key [String] the object name
388
+ # @param query [Hash] query params
389
+ # @option query [String] :response-content-type Specify the header Content-Type in response
390
+ # @option query [String] :response-content-language Specify the header Content-Language in response
391
+ # @option query [String] :response-expires Specify the header Expires in response
392
+ # @option query [String] :response-cache-control Specify the header Cache-Control in response
393
+ # @option query [String] :response-content-disposition Specify the header Content-Disposition in response
394
+ # @option query [String] :response-content-encoding Specify the header Content-encoding in response
395
+ # @param headers [Hash] headers
396
+ # @option headers [String] :Range Specify the range of the file. Such as "bytes=0-9" means the 10 characters from 0 to 9.
397
+ # @option headers [String] :If-Modified-Since If the specified time is earlier than the file last modification time, return 200 OK; Otherwise returns 304(not modified)
398
+ # @option headers [String] :If-Unmodified-Since If the specified time is equal to or later than the file last modification time, normal transfer ans return 200; Otherwise returns 412(precondition)
399
+ # @option headers [String] :If-Match If the specified ETag match the object ETag, normal transfer and return 200; Otherwise return 412(precondition)
400
+ # @option headers [String] :If-None-Match If the specified ETag not match the object ETag, normal transfer and return 200; Otherwise return 304(Not Modified)
401
+ #
402
+ # @return [Response]
403
+ def bucket_get_object(key, query = {}, headers = {})
404
+ http.get("/#{key}", query: query, headers: headers, bucket: bucket, key: key)
405
+ end
406
+
407
+ # Delete object from bucket
408
+ #
409
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&DeleteObject Delete Object
410
+ #
411
+ # @param key [String] the object name
412
+ #
413
+ # @return [Response]
414
+ def bucket_delete_object(key)
415
+ http.delete("/#{key}", bucket: bucket, key: key)
416
+ end
417
+
418
+ # Delete multiple objects, at max 1000 at once
419
+ #
420
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&DeleteMultipleObjects Delete Multiple Objects
421
+ #
422
+ # @param keys [Array<String>] the object names
423
+ # @param quiet [Boolean] Specify response mode: false(Quiet) return results for error objects, true(Verbose) return results of every objects
424
+ #
425
+ # @return [Response]
426
+ def bucket_delete_objects(keys, quiet = false)
427
+ query = { 'delete' => true }
428
+
429
+ key_objects = keys.map { |key| { 'Key' => key } }
430
+ body = Utils.to_xml('Delete' => { 'Object' => key_objects, 'Quiet' => quiet })
431
+
432
+ http.post('/', query: query, body: body, bucket: bucket)
433
+ end
434
+
435
+ # Get meta information of object
436
+ #
437
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&HeadObject Head Object
438
+ #
439
+ # @param key [String] object name
440
+ # @param headers [Hash] headers
441
+ # @option headers [String] :If-Modified-Since If the specified time is earlier than the file last modification time, return 200 OK; Otherwise returns 304(not modified)
442
+ # @option headers [String] :If-Unmodified-Since If the specified time is equal to or later than the file last modification time, normal transfer ans return 200; Otherwise returns 412(precondition)
443
+ # @option headers [String] :If-Match If the specified ETag match the object ETag, normal transfer and return 200; Otherwise return 412(precondition)
444
+ # @option headers [String] :If-None-Match If the specified ETag not match the object ETag, normal transfer and return 200; Otherwise return 304(Not Modified)
445
+ #
446
+ # @return [Response]
447
+ def bucket_get_meta_object(key, headers = {})
448
+ http.head("/#{key}", headers: headers, bucket: bucket, key: key)
449
+ end
450
+
451
+ # Get access of object
452
+ #
453
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&GetObjectACL Get Object ACL
454
+ #
455
+ # @param key [String] object name
456
+ #
457
+ # @return [Response]
458
+ def bucket_get_object_acl(key)
459
+ query = { 'acl' => true }
460
+ http.get("/#{key}", query: query, bucket: bucket, key: key)
461
+ end
462
+
463
+ # Set access of object
464
+ #
465
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/object&PutObjectACL Put Object ACL
466
+ #
467
+ # @param key [String] object name
468
+ # @param acl [String] access value, supported value: private, public-read, public-read-write
469
+ #
470
+ # @return [Response]
471
+ def bucket_set_object_acl(key, acl)
472
+ query = { 'acl' => true }
473
+ headers = { 'x-oss-object-acl' => acl }
474
+ http.put("/#{key}", query: query, headers: headers, bucket: bucket, key: key)
475
+ end
476
+
477
+ # 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.
478
+ #
479
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&InitiateMultipartUpload Initiate Multipart Upload
480
+ #
481
+ # @param key [String] object name
482
+ # @param headers [Hash] headers
483
+ # @option headers [String] :Content-Type ('application/x-www-form-urlencoded') Specify Content-Type for the object
484
+ # @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}
485
+ # @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}
486
+ # @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}
487
+ # @option headers [Integer] :Expires Specify the expiration time (milliseconds)
488
+ # @option headers [String] :x-oss-server-side-encryption Specify the oss server-side encryption algorithm when the object was created. supported value: 'AES256'#
489
+ #
490
+ # @return [Response]
491
+ def bucket_init_multipart(key, headers = {})
492
+ query = { 'uploads' => true }
493
+ http.post("/#{key}", query: query, headers: headers, bucket: bucket, key: key)
494
+ end
495
+
496
+ # Upload object in part.
497
+ #
498
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&UploadPart Upload Part
499
+ #
500
+ # @param key [String] object name
501
+ # @param number [Integer] the part number, Range in 1~10000.
502
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
503
+ # @param file [File, bin data] the upload data
504
+ #
505
+ # @return [Response]
506
+ def bucket_multipart_upload(key, number, upload_id, file)
507
+ fail('number must present!') if number.nil?
508
+ fail('upload_id must present!') if upload_id.nil? || upload_id.empty?
509
+
510
+ query = { 'partNumber' => number.to_s, 'uploadId' => upload_id }
511
+
512
+ http.put("/#{key}", query: query, body: Utils.to_data(file), bucket: bucket, key: key)
513
+ end
514
+
515
+ # Upload a Part from an existing Object Copy data.
516
+ #
517
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&UploadPartCopy Upload Part Copy
518
+ #
519
+ # @param key [String] object name
520
+ # @param number [Integer] the part number, Range in 1~10000.
521
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
522
+ # @param options [Hash] options
523
+ # @option options [String] :source_bucket the source bucket name
524
+ # @option options [String] :source_key the source object name
525
+ # @option options [String] :range the Range bytes, not set means the whole object
526
+ # @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)
527
+ # @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)
528
+ # @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)
529
+ # @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)
530
+ #
531
+ # @return [Response]
532
+ def bucket_multipart_copy_upload(key, number, upload_id, options = {})
533
+ fail('source_bucket must present!') if options[:source_bucket].to_s.empty?
534
+ fail('source_key must present!') if options[:source_key].to_s.empty?
535
+
536
+ query = { 'partNumber' => number, 'uploadId' => upload_id }
537
+
538
+ source_bucket = options.delete(:source_bucket)
539
+ source_key = options.delete(:source_key)
540
+
541
+ headers = {}
542
+ headers.merge!('x-oss-copy-source' => "/#{source_bucket}/#{source_key}")
543
+ headers.merge!('x-oss-copy-source-range' => options.delete(:range)) if options.key?(:range)
544
+ headers.merge!(options)
545
+
546
+ http.put("/#{key}", query: query, headers: headers, bucket: bucket, key: key)
547
+ end
548
+
549
+ # Complete a Multipart Upload event.
550
+ #
551
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&CompleteMultipartUpload Complete Multipart Upload
552
+ #
553
+ # @param key [String] object name
554
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
555
+ # @param parts [Array<Multipart:Part>] parts
556
+ #
557
+ # @return [Response]
558
+ def bucket_complete_multipart(key, upload_id, parts = [])
559
+ fail('parts must present!') if parts.nil? || parts.empty?
560
+ fail('upload_id must present!') if upload_id.nil?
561
+
562
+ query = { 'uploadId' => upload_id }
563
+
564
+ body = Utils.to_xml('CompleteMultipartUpload' => {
565
+ 'Part' => parts.map(&:to_hash)
566
+ })
567
+
568
+ http.post("/#{key}", query: query, body: body, bucket: bucket, key: key)
569
+ end
570
+
571
+ # Abort a Multipart Upload event
572
+ #
573
+ # @note After abort the Multipart Upload, the Uploaded data will be deleted
574
+ # @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.
575
+ #
576
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&AbortMultipartUpload Abort Multipart Upload
577
+ #
578
+ # @param key [String] the object name
579
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
580
+ #
581
+ # @return [Response]
582
+ def bucket_abort_multipart(key, upload_id)
583
+ query = { 'uploadId' => upload_id }
584
+ http.delete("/#{key}", query: query, bucket: bucket, key: key)
585
+ end
586
+
587
+ # List existing opened Multipart Upload event.
588
+ #
589
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&ListMultipartUploads List Multipart Uploads
590
+ #
591
+ # @param options [Hash] options
592
+ # @option options [String] :prefix Filter objects with prefix
593
+ # @option options [String] :delimiter Used to group objects with delimiter
594
+ # @option options [Integer] :max-uploads (1000) Limit number of Multipart Upload events, the maxinum should <= 1000
595
+ # @option options [String] :encoding-type Encoding type used for unsupported character
596
+ # @option options [String] :key-marker with upload-id-marker used to specify the result range.
597
+ # @option options [String] :upload-id-marker with key-marker used to specify the result range.
598
+ #
599
+ # @return [Response]
600
+ def bucket_list_multiparts(options = {})
601
+ accepted_keys = ['prefix', 'key-marker', 'upload-id-marker', 'max-uploads', 'delimiter', 'encoding-type']
602
+
603
+ query = Utils.hash_slice(options, *accepted_keys).merge('uploads' => true)
604
+
605
+ http.get('/', query: query, bucket: bucket)
606
+ end
607
+
608
+ # List uploaded parts for Multipart Upload event
609
+ #
610
+ # @see https://docs.aliyun.com/#/pub/oss/api-reference/multipart-upload&ListParts List Parts
611
+ #
612
+ # @param key [String] the object name
613
+ # @param upload_id [String] the upload ID return by #bucket_init_multipart
614
+ # @param options [Hash] options
615
+ # @option options [Integer] :max-parts (1000) Limit number of parts, the maxinum should <= 1000
616
+ # @option options [Integer] :part-number-marker Specify the start part, return parts which number large than the specified value
617
+ # @option options [String] :encoding-type Encoding type used for unsupported character in xml 1.0
618
+ #
619
+ # @return [Response]
620
+ def bucket_list_parts(key, upload_id, options = {})
621
+ accepted_keys = ['max-parts', 'part-number-marker', 'encoding-type']
622
+
623
+ query = Utils.hash_slice(options, *accepted_keys).merge('uploadId' => upload_id)
624
+
625
+ http.get("/#{key}", query: query, bucket: bucket, key: key)
626
+ end
627
+
628
+ private
629
+
630
+ def http
631
+ @http = Http.new(access_key, secret_key, @options[:host])
632
+ end
633
+ end
634
+ end
635
+ end