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