qiniu_jxb 6.2.4
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.
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +118 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +37 -0
- data/LICENSE +22 -0
- data/README.md +47 -0
- data/Rakefile +21 -0
- data/docs/README.md +790 -0
- data/lib/qiniu-rs.rb +2 -0
- data/lib/qiniu.rb +209 -0
- data/lib/qiniu/abstract.rb +22 -0
- data/lib/qiniu/adt.rb +46 -0
- data/lib/qiniu/auth.rb +234 -0
- data/lib/qiniu/config.rb +58 -0
- data/lib/qiniu/exceptions.rb +120 -0
- data/lib/qiniu/fop.rb +4 -0
- data/lib/qiniu/http.rb +137 -0
- data/lib/qiniu/image.rb +38 -0
- data/lib/qiniu/log.rb +15 -0
- data/lib/qiniu/management.rb +128 -0
- data/lib/qiniu/misc.rb +33 -0
- data/lib/qiniu/pfop.rb +124 -0
- data/lib/qiniu/resumable_upload.rb +319 -0
- data/lib/qiniu/storage.rb +5 -0
- data/lib/qiniu/tokens/access_token.rb +21 -0
- data/lib/qiniu/tokens/download_token.rb +31 -0
- data/lib/qiniu/tokens/qbox_token.rb +38 -0
- data/lib/qiniu/tokens/upload_token.rb +47 -0
- data/lib/qiniu/upload.rb +138 -0
- data/lib/qiniu/utils.rb +109 -0
- data/lib/qiniu/version.rb +17 -0
- data/qiniu.gemspec +29 -0
- data/spec/qiniu/abstract_spec.rb +30 -0
- data/spec/qiniu/auth_spec.rb +81 -0
- data/spec/qiniu/image_logo_for_test.png +0 -0
- data/spec/qiniu/image_spec.rb +89 -0
- data/spec/qiniu/management_spec.rb +156 -0
- data/spec/qiniu/misc_spec.rb +59 -0
- data/spec/qiniu/pfop_spec.rb +89 -0
- data/spec/qiniu/qiniu_spec.rb +329 -0
- data/spec/qiniu/tokens/qbox_token_spec.rb +29 -0
- data/spec/qiniu/upload_spec.rb +308 -0
- data/spec/qiniu/utils_spec.rb +49 -0
- data/spec/qiniu/version_spec.rb +10 -0
- data/spec/spec_helper.rb +19 -0
- metadata +220 -0
data/lib/qiniu/config.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# USAGE WAY 1:
|
4
|
+
# Qbox::Config.initialize_connect :client_id => "<ClientID>",
|
5
|
+
# :client_secret => "<ClientSecret>"
|
6
|
+
#
|
7
|
+
# USAGE WAY 2:
|
8
|
+
# Qbox::Config.load "path/to/your_project/config/qiniu.yml"
|
9
|
+
#
|
10
|
+
|
11
|
+
require 'tmpdir'
|
12
|
+
|
13
|
+
module Qiniu
|
14
|
+
module Config
|
15
|
+
class << self
|
16
|
+
|
17
|
+
DEFAULT_OPTIONS = {
|
18
|
+
:user_agent => 'QiniuRuby/' + Version.to_s + ' ('+RUBY_PLATFORM+')' + ' Ruby/'+ RUBY_VERSION,
|
19
|
+
:method => :post,
|
20
|
+
:content_type => 'application/x-www-form-urlencoded',
|
21
|
+
:auth_url => "https://acc.qbox.me/oauth2/token",
|
22
|
+
:rs_host => "http://rs.qiniu.com",
|
23
|
+
:up_host => "http://up.qiniu.com",
|
24
|
+
:pub_host => "http://pu.qbox.me:10200",
|
25
|
+
:eu_host => "http://eu.qbox.me",
|
26
|
+
:access_key => "",
|
27
|
+
:secret_key => "",
|
28
|
+
:auto_reconnect => true,
|
29
|
+
:max_retry_times => 3,
|
30
|
+
:block_size => 1024*1024*4,
|
31
|
+
:chunk_size => 1024*256,
|
32
|
+
:enable_debug => true,
|
33
|
+
:tmpdir => Dir.tmpdir + File::SEPARATOR + 'QiniuRuby'
|
34
|
+
}
|
35
|
+
|
36
|
+
REQUIRED_OPTION_KEYS = [:access_key, :secret_key]
|
37
|
+
|
38
|
+
attr_reader :settings, :default_params
|
39
|
+
|
40
|
+
def load config_file
|
41
|
+
if File.exist?(config_file)
|
42
|
+
config_options = YAML.load_file(config_file)
|
43
|
+
initialize_connect(config_options)
|
44
|
+
else
|
45
|
+
raise MissingConfError, config_file
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize_connect options = {}
|
50
|
+
@settings = DEFAULT_OPTIONS.merge(options)
|
51
|
+
REQUIRED_OPTION_KEYS.each do |opt|
|
52
|
+
raise MissingArgsError, [opt] unless @settings.has_key?(opt)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end # module Config
|
58
|
+
end # module Qiniu
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Qiniu
|
4
|
+
|
5
|
+
class Exception < RuntimeError
|
6
|
+
end
|
7
|
+
|
8
|
+
class ResponseError < Exception
|
9
|
+
attr_reader :response
|
10
|
+
|
11
|
+
def initialize(message, response = nil)
|
12
|
+
@response = response
|
13
|
+
super(message)
|
14
|
+
end
|
15
|
+
|
16
|
+
def http_code
|
17
|
+
@response.code.to_i if @response
|
18
|
+
end
|
19
|
+
|
20
|
+
def http_body
|
21
|
+
@response.body if @response
|
22
|
+
end
|
23
|
+
|
24
|
+
def inspect
|
25
|
+
"#{message}: #{http_body}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class RequestFailed < ResponseError
|
30
|
+
def message
|
31
|
+
"HTTP status code: #{http_code}. Response body: #{http_body}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
message
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class UploadFailedError < Exception
|
40
|
+
def initialize(status_code, response_data)
|
41
|
+
data_string = response_data.map { |key, value| %Q(:#{key.to_s} => #{value.to_s}) }
|
42
|
+
msg = %Q(Uploading Failed. HTTP Status Code: #{status_code}. HTTP response body: #{data_string.join(', ')}.)
|
43
|
+
super(msg)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class FileSeekReadError < Exception
|
48
|
+
def initialize(fpath, block_index, seek_pos, read_length, result_length)
|
49
|
+
msg = "Reading file: #{fpath}, "
|
50
|
+
msg += "at block index: #{block_index}. "
|
51
|
+
msg += "Expected seek_pos:#{seek_pos} and read_length:#{read_length}, "
|
52
|
+
msg += "but got result_length: #{result_length}."
|
53
|
+
super(msg)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class BlockSizeNotMathchError < Exception
|
58
|
+
def initialize(fpath, block_index, offset, restsize, block_size)
|
59
|
+
msg = "Reading file: #{fpath}, "
|
60
|
+
msg += "at block index: #{block_index}. "
|
61
|
+
msg += "Expected offset: #{offset}, restsize: #{restsize} and block_size: #{block_size}, "
|
62
|
+
msg += "but got offset+restsize=#{offset+restsize}."
|
63
|
+
super(msg)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class BlockCountNotMathchError < Exception
|
68
|
+
def initialize(fpath, block_count, checksum_count, progress_count)
|
69
|
+
msg = "Reading file: #{fpath}, "
|
70
|
+
msg += "Expected block_count, checksum_count, progress_count is: #{block_count}, "
|
71
|
+
msg += "but got checksum_count: #{checksum_count}, progress_count: #{progress_count}."
|
72
|
+
super(msg)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class MissingArgsError < Exception
|
77
|
+
def initialize(missing_keys)
|
78
|
+
key_list = missing_keys.map {|key| key.to_s}.join(' and the ')
|
79
|
+
super("You did not provide both required args. Please provide the #{key_list}.")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class MissingAccessToken < MissingArgsError
|
84
|
+
def initialize
|
85
|
+
super([:access_token])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class MissingRefreshToken < MissingArgsError
|
90
|
+
def initialize
|
91
|
+
super([:refresh_token])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class MissingUsernameOrPassword < MissingArgsError
|
96
|
+
def initialize
|
97
|
+
super([:username, :password])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class InvalidArgsError < Exception
|
102
|
+
def initialize(invalid_keys)
|
103
|
+
key_list = invalid_keys.map {|key| key.to_s}.join(' and the ')
|
104
|
+
super("#{key_list} should not be empty.")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class MissingConfError < Exception
|
109
|
+
def initialize(missing_conf_file)
|
110
|
+
super("Error, missing #{missing_conf_file}. You must have #{missing_conf_file} to configure your client id and secret.")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class NoSuchFileError < Exception
|
115
|
+
def initialize(missing_file)
|
116
|
+
super("Error, no such file #{missing_file}.")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end # module Qiniu
|
data/lib/qiniu/fop.rb
ADDED
data/lib/qiniu/http.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: sw=2 ts=2
|
3
|
+
|
4
|
+
module Qiniu
|
5
|
+
module HTTP
|
6
|
+
|
7
|
+
class << self
|
8
|
+
public
|
9
|
+
def is_response_ok?(http_code)
|
10
|
+
return 200 <= http_code && http_code <= 299
|
11
|
+
end # is_response_ok?
|
12
|
+
|
13
|
+
def generate_query_string(params)
|
14
|
+
if params.is_a?(Hash)
|
15
|
+
total_param = params.map { |key, value| %Q(#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s).gsub('+', '%20')}) }
|
16
|
+
return total_param.join("&")
|
17
|
+
end
|
18
|
+
|
19
|
+
return params
|
20
|
+
end # generate_query_string
|
21
|
+
|
22
|
+
def get (url, opts = {})
|
23
|
+
### 配置请求Header
|
24
|
+
req_headers = {
|
25
|
+
:connection => 'close',
|
26
|
+
:accept => '*/*',
|
27
|
+
:user_agent => Config.settings[:user_agent]
|
28
|
+
}
|
29
|
+
|
30
|
+
# 优先使用外部Header,覆盖任何特定Header
|
31
|
+
if opts[:headers].is_a?(Hash) then
|
32
|
+
req_headers.merge!(opts[:headers])
|
33
|
+
end
|
34
|
+
|
35
|
+
### 发送请求
|
36
|
+
response = RestClient.get(url, req_headers)
|
37
|
+
return response.code.to_i, response.body, response.raw_headers
|
38
|
+
rescue => e
|
39
|
+
Log.logger.warn "#{e.message} => Qiniu::HTTP.get('#{url}')"
|
40
|
+
if e.respond_to?(:response) && e.response.respond_to?(:code) then
|
41
|
+
return e.response.code, e.response.body, e.response.raw_headers
|
42
|
+
end
|
43
|
+
return nil, nil, nil
|
44
|
+
end # get
|
45
|
+
|
46
|
+
API_RESULT_MIMETYPE = 'application/json'
|
47
|
+
|
48
|
+
def api_get (url, opts = {})
|
49
|
+
### 配置请求Header
|
50
|
+
headers = {
|
51
|
+
:accept => API_RESULT_MIMETYPE
|
52
|
+
}
|
53
|
+
|
54
|
+
# 将特定Header混入外部Header中
|
55
|
+
if opts[:headers].is_a?(Hash) then
|
56
|
+
opts[:headers] = opts[:headers].dup.merge!(headers)
|
57
|
+
else
|
58
|
+
opts[:headers] = headers
|
59
|
+
end
|
60
|
+
|
61
|
+
### 发送请求,然后转换返回值
|
62
|
+
resp_code, resp_body, resp_headers = get(url, opts)
|
63
|
+
if resp_code.nil? then
|
64
|
+
return 0, {}, {}
|
65
|
+
end
|
66
|
+
|
67
|
+
content_type = resp_headers["content-type"][0]
|
68
|
+
if !content_type.nil? && content_type == API_RESULT_MIMETYPE then
|
69
|
+
# 如果是JSON格式,则反序列化
|
70
|
+
resp_body = Utils.safe_json_parse(resp_body)
|
71
|
+
end
|
72
|
+
|
73
|
+
return resp_code, resp_body, resp_headers
|
74
|
+
end # api_get
|
75
|
+
|
76
|
+
def post (url, req_body = nil, opts = {})
|
77
|
+
### 配置请求Header
|
78
|
+
req_headers = {
|
79
|
+
:connection => 'close',
|
80
|
+
:accept => '*/*',
|
81
|
+
:user_agent => Config.settings[:user_agent]
|
82
|
+
}
|
83
|
+
|
84
|
+
# 优先使用外部Header,覆盖任何特定Header
|
85
|
+
if opts[:headers].is_a?(Hash) then
|
86
|
+
req_headers.merge!(opts[:headers])
|
87
|
+
end
|
88
|
+
|
89
|
+
### 发送请求
|
90
|
+
response = RestClient.post(url, req_body, req_headers)
|
91
|
+
return response.code.to_i, response.body, response.raw_headers
|
92
|
+
rescue => e
|
93
|
+
Log.logger.warn "#{e.message} => Qiniu::HTTP.post('#{url}')"
|
94
|
+
if e.respond_to?(:response) && e.response.respond_to?(:code) then
|
95
|
+
return e.response.code, e.response.body, e.response.raw_headers
|
96
|
+
end
|
97
|
+
return nil, nil, nil
|
98
|
+
end # post
|
99
|
+
|
100
|
+
def api_post (url, req_body = nil, opts = {})
|
101
|
+
### 配置请求Header
|
102
|
+
headers = {
|
103
|
+
:accept => API_RESULT_MIMETYPE
|
104
|
+
}
|
105
|
+
|
106
|
+
# 将特定Header混入外部Header中
|
107
|
+
if opts[:headers].is_a?(Hash) then
|
108
|
+
opts[:headers] = opts[:headers].dup.merge!(headers)
|
109
|
+
else
|
110
|
+
opts[:headers] = headers
|
111
|
+
end
|
112
|
+
|
113
|
+
### 发送请求,然后转换返回值
|
114
|
+
resp_code, resp_body, resp_headers = post(url, req_body, opts)
|
115
|
+
if resp_code.nil? then
|
116
|
+
return 0, {}, {}
|
117
|
+
end
|
118
|
+
|
119
|
+
content_type = resp_headers["content-type"][0]
|
120
|
+
if !content_type.nil? && content_type == API_RESULT_MIMETYPE then
|
121
|
+
# 如果是JSON格式,则反序列化
|
122
|
+
resp_body = Utils.safe_json_parse(resp_body)
|
123
|
+
end
|
124
|
+
|
125
|
+
return resp_code, resp_body, resp_headers
|
126
|
+
end # api_post
|
127
|
+
|
128
|
+
def management_post (url, body = '')
|
129
|
+
### 授权并执行管理操作
|
130
|
+
return HTTP.api_post(url, body, {
|
131
|
+
:headers => { 'Authorization' => 'QBox ' + Auth.generate_acctoken(url, body) }
|
132
|
+
})
|
133
|
+
end # management_post
|
134
|
+
end # class << self
|
135
|
+
|
136
|
+
end # module HTTP
|
137
|
+
end # module Qiniu
|
data/lib/qiniu/image.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Qiniu
|
4
|
+
module Fop
|
5
|
+
module Image
|
6
|
+
class << self
|
7
|
+
include Utils
|
8
|
+
|
9
|
+
def info(url)
|
10
|
+
return HTTP.api_get(url + '?imageInfo')
|
11
|
+
end # info
|
12
|
+
|
13
|
+
def exif(url)
|
14
|
+
return HTTP.api_get(url + '?exif')
|
15
|
+
end # exif
|
16
|
+
|
17
|
+
def mogrify_preview_url(source_image_url, options)
|
18
|
+
source_image_url + '?' + generate_mogrify_params_string(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_mogrify_params_string(options = {})
|
22
|
+
opts = {}
|
23
|
+
options.each do |k, v|
|
24
|
+
opts[k.to_s] = v
|
25
|
+
end
|
26
|
+
params_string = ""
|
27
|
+
keys = ["thumbnail", "gravity", "crop", "quality", "rotate", "format"]
|
28
|
+
keys.each do |key|
|
29
|
+
params_string += %Q(/#{key}/#{opts[key]}) unless opts[key].nil?
|
30
|
+
end
|
31
|
+
params_string += '/auto-orient' unless opts["auto_orient"].nil?
|
32
|
+
'imageMogr' + URI.escape(params_string)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end # module Image
|
37
|
+
end # module Fop
|
38
|
+
end # module Qiniu
|
data/lib/qiniu/log.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: sw=2 ts=2
|
3
|
+
|
4
|
+
require 'qiniu/http'
|
5
|
+
|
6
|
+
module Qiniu
|
7
|
+
module Storage
|
8
|
+
class << self
|
9
|
+
include Utils
|
10
|
+
|
11
|
+
public
|
12
|
+
def buckets
|
13
|
+
url = Config.settings[:rs_host] + '/buckets'
|
14
|
+
return HTTP.management_post(url)
|
15
|
+
end # buckets
|
16
|
+
|
17
|
+
PRIVATE_BUCKET = 0
|
18
|
+
PUBLIC_BUCKET = 1
|
19
|
+
|
20
|
+
def mkbucket(bucket_name, is_public = PUBLIC_BUCKET)
|
21
|
+
url = Config.settings[:rs_host] + '/mkbucket2/' + bucket_name + '/public/' + is_public.to_s
|
22
|
+
return HTTP.management_post(url)
|
23
|
+
end # mkbucket
|
24
|
+
|
25
|
+
def make_a_private_bucket(bucket_name)
|
26
|
+
return mkbucket(bucket_name, PRIVATE_BUCKET)
|
27
|
+
end # make_a_private_bucket
|
28
|
+
|
29
|
+
def make_a_public_bucket(bucket_name)
|
30
|
+
return mkbucket(bucket_name, PUBLIC_BUCKET)
|
31
|
+
end # make_a_public_bucket
|
32
|
+
|
33
|
+
def stat(bucket, key)
|
34
|
+
url = Config.settings[:rs_host] + '/stat/' + encode_entry_uri(bucket, key)
|
35
|
+
return HTTP.management_post(url)
|
36
|
+
end # stat
|
37
|
+
|
38
|
+
def get(bucket, key, save_as = nil, expires_in = nil, version = nil)
|
39
|
+
url = Config.settings[:rs_host] + '/get/' + encode_entry_uri(bucket, key)
|
40
|
+
url += '/base/' + version unless version.nil?
|
41
|
+
url += '/attName/' + Utils.urlsafe_base64_encode(save_as) unless save_as.nil?
|
42
|
+
url += '/expires/' + expires_in.to_s if !expires_in.nil? && expires_in > 0
|
43
|
+
return HTTP.management_post(url)
|
44
|
+
end # get
|
45
|
+
|
46
|
+
def copy(source_bucket, source_key, target_bucket, target_key)
|
47
|
+
uri = _generate_cp_or_mv_opstr('copy', source_bucket, source_key, target_bucket, target_key)
|
48
|
+
url = Config.settings[:rs_host] + uri
|
49
|
+
return HTTP.management_post(url)
|
50
|
+
end # copy
|
51
|
+
|
52
|
+
def move(source_bucket, source_key, target_bucket, target_key)
|
53
|
+
uri = _generate_cp_or_mv_opstr('move', source_bucket, source_key, target_bucket, target_key)
|
54
|
+
url = Config.settings[:rs_host] + uri
|
55
|
+
return HTTP.management_post(url)
|
56
|
+
end # move
|
57
|
+
|
58
|
+
def delete(bucket, key)
|
59
|
+
url = Config.settings[:rs_host] + '/delete/' + encode_entry_uri(bucket, key)
|
60
|
+
return HTTP.management_post(url)
|
61
|
+
end # delete
|
62
|
+
|
63
|
+
def drop(bucket)
|
64
|
+
url = Config.settings[:rs_host] + "/drop/#{bucket}"
|
65
|
+
return HTTP.management_post(url)
|
66
|
+
end # drop
|
67
|
+
|
68
|
+
def batch(command, bucket, keys)
|
69
|
+
execs = []
|
70
|
+
keys.each do |key|
|
71
|
+
encoded_uri = encode_entry_uri(bucket, key)
|
72
|
+
execs << "op=/#{command}/#{encoded_uri}"
|
73
|
+
end
|
74
|
+
url = Config.settings[:rs_host] + "/batch"
|
75
|
+
return HTTP.management_post(url, execs.join("&"))
|
76
|
+
end # batch
|
77
|
+
|
78
|
+
def batch_get(bucket, keys)
|
79
|
+
batch("get", bucket, keys)
|
80
|
+
end # batch_get
|
81
|
+
|
82
|
+
def batch_stat(bucket, keys)
|
83
|
+
batch("stat", bucket, keys)
|
84
|
+
end # batch_stat
|
85
|
+
|
86
|
+
def batch_copy(*args)
|
87
|
+
_batch_cp_or_mv('copy', args)
|
88
|
+
end # batch_copy
|
89
|
+
|
90
|
+
def batch_move(*args)
|
91
|
+
_batch_cp_or_mv('move', args)
|
92
|
+
end # batch_move
|
93
|
+
|
94
|
+
def batch_delete(bucket, keys)
|
95
|
+
batch("delete", bucket, keys)
|
96
|
+
end # batch_delete
|
97
|
+
|
98
|
+
def save_as(bucket, key, source_url, op_params_string)
|
99
|
+
encoded_uri = encode_entry_uri(bucket, key)
|
100
|
+
save_as_string = '/save-as/' + encoded_uri
|
101
|
+
new_url = source_url + '?' + op_params_string + save_as_string
|
102
|
+
return HTTP.management_post(new_url)
|
103
|
+
end # save_as
|
104
|
+
|
105
|
+
def image_mogrify_save_as(bucket, key, source_image_url, options)
|
106
|
+
mogrify_params_string = Fop::Image.generate_mogrify_params_string(options)
|
107
|
+
save_as(bucket, key, source_image_url, mogrify_params_string)
|
108
|
+
end # image_mogrify_save_as
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def _generate_cp_or_mv_opstr(command, source_bucket, source_key, target_bucket, target_key)
|
113
|
+
source_encoded_entry_uri = encode_entry_uri(source_bucket, source_key)
|
114
|
+
target_encoded_entry_uri = encode_entry_uri(target_bucket, target_key)
|
115
|
+
%Q(/#{command}/#{source_encoded_entry_uri}/#{target_encoded_entry_uri})
|
116
|
+
end # _generate_cp_or_mv_opstr
|
117
|
+
|
118
|
+
def _batch_cp_or_mv(command, *op_args)
|
119
|
+
execs = []
|
120
|
+
op_args.each do |e|
|
121
|
+
execs << 'op=' + _generate_cp_or_mv_opstr(command, e[0], e[1], e[2], e[3]) if e.size == 4
|
122
|
+
end
|
123
|
+
url = Config.settings[:rs_host] + "/batch"
|
124
|
+
return HTTP.management_post(url, execs.join("&"))
|
125
|
+
end # _batch_cp_or_mv
|
126
|
+
end
|
127
|
+
end # module Storage
|
128
|
+
end # module Qiniu
|