fog-aliyun 0.3.18 → 0.3.19

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