fog-aliyun 0.3.18 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -1
  3. data/fog-aliyun.gemspec +2 -2
  4. data/lib/fog/aliyun/models/storage/directories.rb +30 -53
  5. data/lib/fog/aliyun/models/storage/directory.rb +96 -17
  6. data/lib/fog/aliyun/models/storage/file.rb +127 -126
  7. data/lib/fog/aliyun/models/storage/files.rb +48 -127
  8. data/lib/fog/aliyun/requests/storage/abort_multipart_upload.rb +22 -0
  9. data/lib/fog/aliyun/requests/storage/complete_multipart_upload.rb +21 -0
  10. data/lib/fog/aliyun/requests/storage/copy_object.rb +14 -18
  11. data/lib/fog/aliyun/requests/storage/delete_bucket.rb +3 -9
  12. data/lib/fog/aliyun/requests/storage/delete_multiple_objects.rb +20 -0
  13. data/lib/fog/aliyun/requests/storage/delete_object.rb +10 -11
  14. data/lib/fog/aliyun/requests/storage/get_bucket.rb +22 -99
  15. data/lib/fog/aliyun/requests/storage/get_bucket_location.rb +33 -0
  16. data/lib/fog/aliyun/requests/storage/get_object.rb +20 -12
  17. data/lib/fog/aliyun/requests/storage/get_object_acl.rb +30 -0
  18. data/lib/fog/aliyun/requests/storage/get_object_http_url.rb +6 -9
  19. data/lib/fog/aliyun/requests/storage/get_object_https_url.rb +6 -9
  20. data/lib/fog/aliyun/requests/storage/get_service.rb +13 -0
  21. data/lib/fog/aliyun/requests/storage/head_object.rb +25 -13
  22. data/lib/fog/aliyun/requests/storage/initiate_multipart_upload.rb +19 -0
  23. data/lib/fog/aliyun/requests/storage/list_buckets.rb +5 -25
  24. data/lib/fog/aliyun/requests/storage/list_objects.rb +10 -62
  25. data/lib/fog/aliyun/requests/storage/put_bucket.rb +2 -8
  26. data/lib/fog/aliyun/requests/storage/put_object.rb +16 -122
  27. data/lib/fog/aliyun/requests/storage/upload_part.rb +24 -0
  28. data/lib/fog/aliyun/storage.rb +20 -4
  29. data/lib/fog/aliyun/version.rb +1 -1
  30. metadata +14 -10
  31. data/lib/fog/aliyun/requests/storage/delete_container.rb +0 -30
  32. data/lib/fog/aliyun/requests/storage/get_container.rb +0 -57
  33. data/lib/fog/aliyun/requests/storage/get_containers.rb +0 -61
  34. data/lib/fog/aliyun/requests/storage/put_container.rb +0 -29
@@ -0,0 +1,33 @@
1
+ require 'nokogiri'
2
+ module Fog
3
+ module Aliyun
4
+ class Storage
5
+ class Real
6
+
7
+ # Get location constraint for an OSS bucket
8
+ #
9
+ # @param bucket_name [String] name of bucket to get location constraint for
10
+ #
11
+ # @see https://help.aliyun.com/document_detail/31967.html
12
+ #
13
+ # note: The OSS Ruby sdk does not support get_bucket_location and there needs to parse response
14
+
15
+ def get_bucket_location(bucket_name)
16
+ data = @oss_http.get({:bucket => bucket_name, :sub_res => { 'location' => nil} }, {})
17
+ doc = parse_xml(data.body)
18
+ doc.at_css("LocationConstraint").text
19
+ end
20
+
21
+ private
22
+
23
+ def parse_xml(content)
24
+ doc = Nokogiri::XML(content) do |config|
25
+ config.options |= Nokogiri::XML::ParseOptions::NOBLANKS
26
+ end
27
+
28
+ doc
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -7,30 +7,38 @@ module Fog
7
7
  # Get details for object
8
8
  #
9
9
  # ==== Parameters
10
- # * object<~String> - Name of object to look for
10
+ # * object_name<~String> - Name of object to look for
11
11
  #
12
- def get_object(object, options = {}, &block)
12
+ def get_object(bucket_name, object_name, options = {}, &block)
13
13
  options = options.reject { |_key, value| value.nil? }
14
- bucket_name = options[:bucket]
15
- bucket_name ||= @aliyun_oss_bucket
16
- options.delete(:bucket)
14
+ unless bucket_name
15
+ raise ArgumentError.new('bucket_name is required')
16
+ end
17
+ unless object_name
18
+ raise ArgumentError.new('object_name is required')
19
+ end
17
20
  # Using OSS ruby SDK to fix performance issue
18
- params = { :headers => {} }
19
- params[:query] = options.delete('query') || {}
21
+ http_options = { :headers => {} }
22
+ http_options[:query] = options.delete('query') || {}
20
23
 
21
- params[:headers].merge!(options)
24
+ http_options[:headers].merge!(options)
22
25
  if options['If-Modified-Since']
23
- params[:headers]['If-Modified-Since'] = Fog::Time.at(options['If-Modified-Since'].to_i).to_date_header
26
+ http_options[:headers]['If-Modified-Since'] = Fog::Time.at(options['If-Modified-Since'].to_i).to_date_header
24
27
  end
25
28
  if options['If-Unmodified-Since']
26
- params[:headers]['If-Unmodified-Since'] = Fog::Time.at(options['If-Unmodified-Since'].to_i).to_date_header
29
+ http_options[:headers]['If-Unmodified-Since'] = Fog::Time.at(options['If-Unmodified-Since'].to_i).to_date_header
27
30
  end
28
31
 
29
32
  if block_given?
30
- params[:response_block] = Proc.new
33
+ http_options[:response_block] = Proc.new
31
34
  end
32
35
 
33
- @oss_http.get({:bucket => bucket_name, :object => object}, params, &block)
36
+ resources = {
37
+ :bucket => bucket_name,
38
+ :object => object_name
39
+ }
40
+
41
+ @oss_http.get(resources, http_options, &block)
34
42
 
35
43
  end
36
44
  end
@@ -0,0 +1,30 @@
1
+ module Fog
2
+ module Aliyun
3
+ class Storage
4
+ class Real
5
+
6
+ # Get access control list for an S3 object
7
+ #
8
+ # @param bucket_name [String] name of bucket containing object
9
+ # @param object_name [String] name of object to get access control list for
10
+ # @param options [Hash]
11
+ # @option options versionId [String] specify a particular version to retrieve
12
+
13
+ def get_object_acl(bucket_name, object_name, options = {})
14
+ unless bucket_name
15
+ raise ArgumentError.new('bucket_name is required')
16
+ end
17
+ unless object_name
18
+ raise ArgumentError.new('object_name is required')
19
+ end
20
+
21
+ # At present, sdk does not support versionId
22
+ # if version_id = options.delete('versionId')
23
+ # query['versionId'] = version_id
24
+ # end
25
+ @oss_protocol.get_object_acl(bucket_name, object_name)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -7,29 +7,26 @@ module Fog
7
7
  # Get an expiring object http url
8
8
  #
9
9
  # ==== Parameters
10
- # * container<~String> - Name of container containing object
11
- # * object<~String> - Name of object to get expiring url for
10
+ # * bucket_name<~String> - Name of bucket
11
+ # * object_name<~String> - Name of object to get expiring url for
12
12
  # * expires<~Integer> - An expiry time for this url
13
13
  #
14
14
  # ==== Returns
15
15
  # * response<~Excon::Response>:
16
16
  # * body<~String> - url for object
17
- def get_object_http_url_public(object, expires, options = {})
18
- options = options.reject { |_key, value| value.nil? }
19
- bucket_name = options[:bucket]
20
- bucket_name ||= @aliyun_oss_bucket
17
+ def get_object_http_url_public(bucket_name, object_name, expires)
21
18
  bucket = @oss_client.get_bucket(bucket_name)
22
19
  acl = bucket.acl()
23
20
 
24
21
  if acl == 'private'
25
22
  expires_time = (Time.now.to_i + (expires.nil? ? 0 : expires.to_i)).to_s
26
- resource = bucket_name + '/' + object
23
+ resource = bucket_name + '/' + object_name
27
24
  signature = sign('GET', expires_time, nil, resource)
28
- 'http://' + bucket_name + '.' + @host + '/' + object +
25
+ 'http://' + bucket_name + '.' + @host + '/' + object_name +
29
26
  '?OSSAccessKeyId=' + @aliyun_accesskey_id + '&Expires=' + expires_time +
30
27
  '&Signature=' + URI.encode(signature, '/[^!*\'()\;?:@#&%=+$,{}[]<>`" ')
31
28
  elsif acl == 'public-read' || acl == 'public-read-write'
32
- 'http://' + bucket_name + '.' + @host + '/' + object
29
+ 'http://' + bucket_name + '.' + @host + '/' + object_name
33
30
  else
34
31
  'acl is wrong with value:' + acl
35
32
  end
@@ -7,29 +7,26 @@ module Fog
7
7
  # Get an expiring object https url from Cloud Files
8
8
  #
9
9
  # ==== Parameters
10
- # * container<~String> - Name of container containing object
11
- # * object<~String> - Name of object to get expiring url for
10
+ # * bucket_name<~String> - Name of bucket
11
+ # * object_name<~String> - Name of object to get expiring url for
12
12
  # * expires<~Integer> - An expiry time for this url
13
13
  #
14
14
  # ==== Returns
15
15
  # * response<~Excon::Response>:
16
16
  # * body<~String> - url for object
17
- def get_object_https_url_public(object, expires, options = {})
18
- options = options.reject { |_key, value| value.nil? }
19
- bucket_name = options[:bucket]
20
- bucket_name ||= @aliyun_oss_bucket
17
+ def get_object_https_url_public(bucket_name, object_name, expires)
21
18
  bucket = @oss_client.get_bucket(bucket_name)
22
19
  acl = bucket.acl()
23
20
 
24
21
  if acl == 'private'
25
22
  expires_time = (Time.now.to_i + (expires.nil? ? 0 : expires.to_i)).to_s
26
- resource = bucket_name + '/' + object
23
+ resource = bucket_name + '/' + object_name
27
24
  signature = sign('GET', expires_time, nil, resource)
28
- 'https://' + bucket_name + '.' + @host + '/' + object +
25
+ 'https://' + bucket_name + '.' + @host + '/' + object_name +
29
26
  '?OSSAccessKeyId=' + @aliyun_accesskey_id + '&Expires=' + expires_time +
30
27
  '&Signature=' + URI.encode(signature, '/[^!*\'()\;?:@#&%=+$,{}[]<>`" ')
31
28
  elsif acl == 'public-read' || acl == 'public-read-write'
32
- 'https://' + bucket_name + '.' + @host + '/' + object
29
+ 'https://' + bucket_name + '.' + @host + '/' + object_name
33
30
  else
34
31
  'acl is wrong with value:' + acl
35
32
  end
@@ -0,0 +1,13 @@
1
+ module Fog
2
+ module Aliyun
3
+ class Storage
4
+ class Real
5
+ # List information about OSS buckets for authorized user
6
+ #
7
+ def get_service
8
+ @oss_protocol.list_buckets
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -7,20 +7,32 @@ module Fog
7
7
  # Get headers for object
8
8
  #
9
9
  # ==== Parameters
10
- # * object<~String> - Name of object to look for
10
+ # * object_name<~String> - Name of object to look for
11
11
  #
12
- def head_object(object, options = {})
13
- bucket_name = options[:bucket]
14
- bucket_name ||= @aliyun_oss_bucket
15
- resource = bucket_name + '/' + object
16
- ret = request(
17
- expects: [200, 404],
18
- method: 'HEAD',
19
- path: object,
20
- bucket: bucket_name,
21
- resource: resource
22
- )
23
- ret
12
+ def head_object(bucket_name, object_name, options={})
13
+ unless bucket_name
14
+ raise ArgumentError.new('bucket_name is required')
15
+ end
16
+ unless object_name
17
+ raise ArgumentError.new('object_name is required')
18
+ end
19
+
20
+ # Currently, the ruby sdk does not support versionId
21
+ # if version_id = options.delete('versionId')
22
+ # query = {'versionId' => version_id}
23
+ # end
24
+ headers = {}
25
+ headers['If-Modified-Since'] = Fog::Time.at(options['If-Modified-Since'].to_i).to_date_header if options['If-Modified-Since']
26
+ headers['If-Unmodified-Since'] = Fog::Time.at(options['If-Unmodified-Since'].to_i).to_date_header if options['If-Modified-Since']
27
+ headers.merge!(options)
28
+ resources = {
29
+ :bucket => bucket_name,
30
+ :object => object_name
31
+ }
32
+ http_options = {
33
+ :headers => headers
34
+ }
35
+ @oss_http.head(resources, http_options)
24
36
  end
25
37
  end
26
38
  end
@@ -0,0 +1,19 @@
1
+ module Fog
2
+ module Aliyun
3
+ class Storage
4
+ class Real
5
+ # Initiate a multipart upload
6
+ #
7
+ # @param bucket_name [String] Name of bucket to create
8
+ # @param object_name [String] Name of object to create
9
+ # @param options [Hash]
10
+ #
11
+ # @see https://help.aliyun.com/document_detail/31992.html
12
+ #
13
+ def initiate_multipart_upload(bucket_name, object_name, options = {})
14
+ @oss_protocol.initiate_multipart_upload(bucket_name, object_name, options)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,33 +5,13 @@ module Fog
5
5
  class Storage
6
6
  class Real
7
7
  def list_buckets(options = {})
8
- prefix = options[:prefix]
9
- marker = options[:marker]
10
- maxKeys = options[:maxKeys] || 1000
8
+ maxKeys = options[:max_keys] || 1000
11
9
  maxKeys = maxKeys.to_i
12
- maxKeys =[maxKeys,1000].min.to_s
10
+ maxKeys = [maxKeys, 1000].min
13
11
 
14
- path = ''
15
- if prefix
16
- path += '?prefix=' + prefix
17
- path += '&marker=' + marker if marker
18
- path += '&max-keys=' + maxKeys if maxKeys
19
-
20
- elsif marker
21
- path += '?marker=' + marker
22
- path += '&max-keys=' + maxKeys if maxKeys
23
-
24
- elsif maxKeys
25
- path += '?max-keys=' + maxKeys
26
- end
27
-
28
- ret = request(
29
- expects: [200, 203],
30
- method: 'GET',
31
- path: path
32
- )
33
- xml = ret.data[:body]
34
- XmlSimple.xml_in(xml)['Buckets'][0]
12
+ options[:limit] = maxKeys
13
+ options.delete(:max_keys)
14
+ @oss_protocol.list_buckets(options)
35
15
  end
36
16
  end
37
17
  end
@@ -4,74 +4,22 @@ module Fog
4
4
  module Aliyun
5
5
  class Storage
6
6
  class Real
7
- def list_objects(options = {})
8
- bucket = options['bucket']
9
- bucket ||= @aliyun_oss_bucket
10
- prefix = options['prefix']
11
- marker = options['marker']
12
- # Set the ListObjects max limitation to 1000
13
- maxKeys = options[:maxKeys]||1000
7
+ def list_objects(bucket_name, options = {})
8
+ maxKeys = options[:max_keys] || 1000
14
9
  maxKeys = maxKeys.to_i
15
- maxKeys = [maxKeys,1000].min.to_s
16
- delimiter = options['delimiter']
10
+ maxKeys = [maxKeys, 1000].min
17
11
 
18
- path = ''
19
- if prefix
20
- path += '/?prefix=' + prefix
21
- path += '&marker=' + marker if marker
22
- path += '&max-keys=' + maxKeys if maxKeys
23
- path += '&delimiter=' + delimiter if delimiter
24
-
25
- elsif marker
26
- path += '/?marker=' + marker
27
- path += '&max-keys=' + maxKeys if maxKeys
28
- path += '&delimiter=' + delimiter if delimiter
29
-
30
- elsif maxKeys
31
- path += '/?max-keys=' + maxKeys
32
- path += '&delimiter=' + delimiter if delimiter
33
- elsif delimiter
34
- path += '/?delimiter=' + delimiter
35
- end
36
-
37
- resource = bucket + '/'
38
- ret = request(
39
- expects: [200, 203, 400],
40
- method: 'GET',
41
- path: path,
42
- resource: resource,
43
- bucket: bucket
44
- )
45
- xml = ret.data[:body]
46
- XmlSimple.xml_in(xml)
12
+ options[:limit] = maxKeys
13
+ options.delete(:max_keys)
14
+ @oss_protocol.list_objects(bucket_name, options)
47
15
  end
48
16
 
49
- def list_multipart_uploads(bucket, _options = {})
50
- path = '?uploads'
51
- resource = bucket + '/' + path
52
-
53
- ret = request(
54
- expects: 200,
55
- method: 'GET',
56
- path: path,
57
- bucket: bucket,
58
- resource: resource
59
- )
60
- XmlSimple.xml_in(ret.data[:body])['Upload']
17
+ def list_multipart_uploads(bucket_name, _options = {})
18
+ @oss_protocol.list_multipart_uploads(bucket_name, _options)
61
19
  end
62
20
 
63
- def list_parts(bucket, object, uploadid, _options = {})
64
- path = object + '?uploadId=' + uploadid
65
- resource = bucket + '/' + path
66
-
67
- ret = request(
68
- expects: 200,
69
- method: 'GET',
70
- path: path,
71
- bucket: bucket,
72
- resource: resource
73
- )
74
- XmlSimple.xml_in(ret.data[:body])['Part']
21
+ def list_parts(bucket_name, object_name, upload_id, _options = {})
22
+ @oss_protocol.list_parts(bucket_name, object_name, upload_id, _options)
75
23
  end
76
24
  end
77
25
  end
@@ -4,14 +4,8 @@ module Fog
4
4
  module Aliyun
5
5
  class Storage
6
6
  class Real
7
- def put_bucket(bucketName)
8
- resource = bucketName + '/'
9
- request(
10
- expects: [200, 203],
11
- method: 'PUT',
12
- resource: resource,
13
- bucket: bucketName
14
- )
7
+ def put_bucket(bucket_name, options = {})
8
+ @oss_protocol.create_bucket(bucket_name, options)
15
9
  end
16
10
  end
17
11
  end
@@ -7,133 +7,27 @@ module Fog
7
7
  # Put details for object
8
8
  #
9
9
  # ==== Parameters
10
- # * object<~String> - Name of object to look for
10
+ # * bucket_name<~String> - Name of bucket to look for
11
+ # * object_name<~String> - Object of object to look for
12
+ # * data<~File>
13
+ # * options<~Hash>
11
14
  #
12
- def put_object(object, file = nil, options = {})
13
- bucket_name = options[:bucket]
14
- bucket_name ||= @aliyun_oss_bucket
15
- bucket = @oss_client.get_bucket(bucket_name)
16
- return bucket.put_object(object) if file.nil?
17
- # With a single PUT operation you can upload objects up to 5 GB in size.
18
- if file.size > 5_368_709_120
19
- bucket.resumable_upload(object, file.path)
20
- end
21
- bucket.put_object(object, :file => file.path)
22
- end
23
-
24
- def put_object_with_body(object, body, options = {})
25
- bucket_name = options[:bucket]
26
- bucket_name ||= @aliyun_oss_bucket
27
-
28
- resource = bucket_name + '/' + object
29
- request(
30
- expects: [200, 203],
31
- method: 'PUT',
32
- path: object,
33
- bucket: bucket_name,
34
- resource: resource,
35
- body: body
36
- )
37
- end
38
-
39
- def put_folder(bucket, folder)
40
- path = folder + '/'
41
- resource = bucket + '/' + folder + '/'
42
- request(
43
- expects: [200, 203],
44
- method: 'PUT',
45
- path: path,
46
- bucket: bucket,
47
- resource: resource
48
- )
49
- end
50
-
51
- def put_multipart_object(bucket, object, file)
52
- # find the right uploadid
53
- uploads = list_multipart_uploads(bucket)
54
- upload = (uploads&.find { |tmpupload| tmpupload['Key'][0] == object })
55
-
56
- uploadedSize = 0
57
- start_partNumber = 1
58
- if !upload.nil?
59
- uploadId = upload['UploadId'][0]
60
- parts = list_parts(bucket, object, uploadId)
61
- if !parts.nil? && !parts.empty?
62
- if parts[-1]['Size'][0].to_i != 5_242_880
63
- # the part is the last one, if its size is over 5m, then finish this upload
64
- complete_multipart_upload(bucket, object, uploadId)
65
- return
15
+ def put_object(bucket_name, object_name, data, options = {})
16
+ if data.is_a? ::File
17
+ @oss_protocol.put_object(bucket_name, object_name, options)do |sw|
18
+ while line = data.read(16*1024)
19
+ sw.write(line)
66
20
  end
67
- uploadedSize = (parts[0]['Size'][0].to_i * (parts.size - 1)) + parts[-1]['Size'][0].to_i
68
- start_partNumber = parts[-1]['PartNumber'][0].to_i + 1
69
21
  end
70
22
  else
71
- # create upload ID
72
- uploadId = initiate_multipart_upload(bucket, object)
73
- end
74
-
75
- if file.size <= uploadedSize
76
- complete_multipart_upload(bucket, object, uploadId)
77
- return
78
- end
79
-
80
- end_partNumber = (file.size + 5_242_880 - 1) / 5_242_880
81
- file.seek(uploadedSize)
82
-
83
- for i in start_partNumber..end_partNumber
84
- body = file.read(5_242_880)
85
- upload_part(bucket, object, i.to_s, uploadId, body)
86
- end
87
-
88
- complete_multipart_upload(bucket, object, uploadId)
89
- end
90
-
91
- def initiate_multipart_upload(bucket, object)
92
- path = object + '?uploads'
93
- resource = bucket + '/' + path
94
- ret = request(
95
- expects: 200,
96
- method: 'POST',
97
- path: path,
98
- bucket: bucket,
99
- resource: resource
100
- )
101
- XmlSimple.xml_in(ret.data[:body])['UploadId'][0]
102
- end
103
-
104
- def upload_part(bucket, object, partNumber, uploadId, body)
105
- path = object + '?partNumber=' + partNumber + '&uploadId=' + uploadId
106
- resource = bucket + '/' + path
107
- request(
108
- expects: [200, 203],
109
- method: 'PUT',
110
- path: path,
111
- bucket: bucket,
112
- resource: resource,
113
- body: body
114
- )
115
- end
116
-
117
- def complete_multipart_upload(bucket, object, uploadId)
118
- parts = list_parts(bucket, object, uploadId, options = {})
119
- request_part = []
120
- return if parts.empty?
121
- for i in 0..(parts.size - 1)
122
- part = parts[i]
123
- request_part[i] = { 'PartNumber' => part['PartNumber'], 'ETag' => part['ETag'] }
23
+ content=StringIO.new(data.dup)
24
+ @oss_protocol.put_object(bucket_name, object_name, options)do |sw|
25
+ while line=content.read(16*1024)
26
+ sw.write(line)
27
+ end
28
+ end
29
+ content.close
124
30
  end
125
- body = XmlSimple.xml_out({ 'Part' => request_part }, 'RootName' => 'CompleteMultipartUpload')
126
-
127
- path = object + '?uploadId=' + uploadId
128
- resource = bucket + '/' + path
129
- request(
130
- expects: 200,
131
- method: 'POST',
132
- path: path,
133
- bucket: bucket,
134
- resource: resource,
135
- body: body
136
- )
137
31
  end
138
32
  end
139
33
  end