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-rs.rb
ADDED
data/lib/qiniu.rb
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Qiniu
|
4
|
+
autoload :Version, 'qiniu/version'
|
5
|
+
autoload :Utils, 'qiniu/utils'
|
6
|
+
autoload :Auth, 'qiniu/auth'
|
7
|
+
autoload :Config, 'qiniu/config'
|
8
|
+
autoload :Log, 'qiniu/log'
|
9
|
+
autoload :Exception, 'qiniu/exceptions'
|
10
|
+
autoload :AccessToken, 'qiniu/tokens/access_token'
|
11
|
+
autoload :QboxToken, 'qiniu/tokens/qbox_token'
|
12
|
+
autoload :UploadToken, 'qiniu/tokens/upload_token'
|
13
|
+
autoload :DownloadToken, 'qiniu/tokens/download_token'
|
14
|
+
autoload :Abstract, 'qiniu/abstract'
|
15
|
+
autoload :Storage, 'qiniu/storage'
|
16
|
+
autoload :Fop, 'qiniu/fop'
|
17
|
+
autoload :Misc, 'qiniu/misc'
|
18
|
+
|
19
|
+
class << self
|
20
|
+
|
21
|
+
StatusOK = 200
|
22
|
+
|
23
|
+
def establish_connection!(opts = {})
|
24
|
+
Config.initialize_connect opts
|
25
|
+
end
|
26
|
+
|
27
|
+
def mkbucket(bucket_name)
|
28
|
+
code, data = Storage.mkbucket(bucket_name)
|
29
|
+
code == StatusOK
|
30
|
+
end
|
31
|
+
|
32
|
+
def buckets
|
33
|
+
code, data = Storage.buckets
|
34
|
+
code == StatusOK ? data : false
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_protected(bucket, protected_mode)
|
38
|
+
code, data = Misc.set_protected(bucket, protected_mode)
|
39
|
+
code == StatusOK
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_separator(bucket, separator)
|
43
|
+
code, data = Misc.set_separator(bucket, separator)
|
44
|
+
code == StatusOK
|
45
|
+
end
|
46
|
+
|
47
|
+
def set_style(bucket, name, style)
|
48
|
+
code, data = Misc.set_style(bucket, name, style)
|
49
|
+
code == StatusOK
|
50
|
+
end
|
51
|
+
|
52
|
+
def unset_style(bucket, name)
|
53
|
+
code, data = Misc.unset_style(bucket, name)
|
54
|
+
code == StatusOK
|
55
|
+
end
|
56
|
+
|
57
|
+
def upload_file opts = {}
|
58
|
+
uncontained_opts = [:uptoken, :file, :bucket, :key] - opts.keys
|
59
|
+
raise MissingArgsError, uncontained_opts unless uncontained_opts.empty?
|
60
|
+
|
61
|
+
source_file = opts[:file]
|
62
|
+
raise NoSuchFileError, source_file unless File.exist?(source_file)
|
63
|
+
|
64
|
+
opts[:enable_resumable_upload] = true unless opts.has_key?(:enable_resumable_upload)
|
65
|
+
|
66
|
+
if opts[:enable_resumable_upload] && File::size(source_file) > Config.settings[:block_size]
|
67
|
+
code, data, raw_headers = Storage.upload_with_token(opts[:uptoken],
|
68
|
+
opts[:file],
|
69
|
+
opts[:bucket],
|
70
|
+
opts[:key],
|
71
|
+
opts[:mime_type],
|
72
|
+
opts[:note],
|
73
|
+
opts[:customer],
|
74
|
+
opts[:callback_params],
|
75
|
+
opts[:rotate])
|
76
|
+
else
|
77
|
+
code, data, raw_headers = Storage.upload_with_token(opts[:uptoken],
|
78
|
+
opts[:file],
|
79
|
+
opts[:bucket],
|
80
|
+
opts[:key],
|
81
|
+
opts[:mime_type],
|
82
|
+
opts[:note],
|
83
|
+
opts[:callback_params],
|
84
|
+
opts[:enable_crc32_check],
|
85
|
+
opts[:rotate])
|
86
|
+
end
|
87
|
+
raise UploadFailedError.new(code, data) if code != StatusOK
|
88
|
+
return data
|
89
|
+
end
|
90
|
+
|
91
|
+
def stat(bucket, key)
|
92
|
+
code, data = Storage.stat(bucket, key)
|
93
|
+
code == StatusOK ? data : false
|
94
|
+
end
|
95
|
+
|
96
|
+
def get(bucket, key, save_as = nil, expires_in = nil, version = nil)
|
97
|
+
code, data = Storage.get(bucket, key, save_as, expires_in, version)
|
98
|
+
code == StatusOK ? data : false
|
99
|
+
end
|
100
|
+
|
101
|
+
def download(bucket, key, save_as = nil, expires_in = nil, version = nil)
|
102
|
+
code, data = Storage.get(bucket, key, save_as, expires_in, version)
|
103
|
+
code == StatusOK ? data["url"] : false
|
104
|
+
end
|
105
|
+
|
106
|
+
def copy(source_bucket, source_key, target_bucket, target_key)
|
107
|
+
code, data = Storage.copy(source_bucket, source_key, target_bucket, target_key)
|
108
|
+
code == StatusOK
|
109
|
+
end
|
110
|
+
|
111
|
+
def move(source_bucket, source_key, target_bucket, target_key)
|
112
|
+
code, data = Storage.move(source_bucket, source_key, target_bucket, target_key)
|
113
|
+
code == StatusOK
|
114
|
+
end
|
115
|
+
|
116
|
+
def delete(bucket, key)
|
117
|
+
code, data = Storage.delete(bucket, key)
|
118
|
+
code == StatusOK
|
119
|
+
end
|
120
|
+
|
121
|
+
def batch(command, bucket, keys)
|
122
|
+
code, data = Storage.batch(command, bucket, keys)
|
123
|
+
code == StatusOK ? data : false
|
124
|
+
end
|
125
|
+
|
126
|
+
def batch_stat(bucket, keys)
|
127
|
+
code, data = Storage.batch_stat(bucket, keys)
|
128
|
+
code == StatusOK ? data : false
|
129
|
+
end
|
130
|
+
|
131
|
+
def batch_get(bucket, keys)
|
132
|
+
code, data = Storage.batch_get(bucket, keys)
|
133
|
+
code == StatusOK ? data : false
|
134
|
+
end
|
135
|
+
|
136
|
+
def batch_copy(*args)
|
137
|
+
code, data = Storage.batch_copy(args)
|
138
|
+
code == StatusOK
|
139
|
+
end
|
140
|
+
|
141
|
+
def batch_move(*args)
|
142
|
+
code, data = Storage.batch_move(args)
|
143
|
+
code == StatusOK
|
144
|
+
end
|
145
|
+
|
146
|
+
def batch_download(bucket, keys)
|
147
|
+
code, data = Storage.batch_get(bucket, keys)
|
148
|
+
return false unless code == StatusOK
|
149
|
+
links = []
|
150
|
+
data.each { |e| links << e["data"]["url"] }
|
151
|
+
links
|
152
|
+
end
|
153
|
+
|
154
|
+
def batch_delete(bucket, keys)
|
155
|
+
code, data = Storage.batch_delete(bucket, keys)
|
156
|
+
code == StatusOK ? data : false
|
157
|
+
end
|
158
|
+
|
159
|
+
def drop(bucket)
|
160
|
+
code, data = Storage.drop(bucket)
|
161
|
+
code == StatusOK
|
162
|
+
end
|
163
|
+
|
164
|
+
def image_info(url)
|
165
|
+
code, data = Fop::Image.info(url)
|
166
|
+
code == StatusOK ? data : false
|
167
|
+
end
|
168
|
+
|
169
|
+
def image_exif(url)
|
170
|
+
code, data = Fop::Image.exif(url)
|
171
|
+
code == StatusOK ? data : false
|
172
|
+
end
|
173
|
+
|
174
|
+
def image_mogrify_preview_url(source_image_url, options)
|
175
|
+
Fop::Image.mogrify_preview_url(source_image_url, options)
|
176
|
+
end
|
177
|
+
|
178
|
+
def image_mogrify_save_as(bucket, key, source_image_url, options)
|
179
|
+
code, data = Storage.image_mogrify_save_as(bucket, key, source_image_url, options)
|
180
|
+
code == StatusOK ? data : false
|
181
|
+
end
|
182
|
+
|
183
|
+
def generate_upload_token(opts = {})
|
184
|
+
token_obj = UploadToken.new(opts)
|
185
|
+
token_obj.access_key = Config.settings[:access_key]
|
186
|
+
token_obj.secret_key = Config.settings[:secret_key]
|
187
|
+
#token_obj.scope = opts[:scope]
|
188
|
+
#token_obj.expires_in = opts[:expires_in]
|
189
|
+
#token_obj.callback_url = opts[:callback_url]
|
190
|
+
#token_obj.callback_body_type = opts[:callback_body_type]
|
191
|
+
#token_obj.customer = opts[:customer]
|
192
|
+
#token_obj.escape = opts[:escape]
|
193
|
+
#token_obj.async_options = opts[:async_options]
|
194
|
+
#token_obj.return_body = opts[:return_body]
|
195
|
+
token_obj.generate_token
|
196
|
+
end
|
197
|
+
|
198
|
+
def generate_download_token(opts = {})
|
199
|
+
token_obj = DownloadToken.new(opts)
|
200
|
+
token_obj.access_key = Config.settings[:access_key]
|
201
|
+
token_obj.secret_key = Config.settings[:secret_key]
|
202
|
+
#token_obj.expires_in = opts[:expires_in]
|
203
|
+
#token_obj.pattern = opts[:pattern]
|
204
|
+
token_obj.generate_token
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
end # module Qiniu
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Qiniu
|
4
|
+
module Abstract
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def abstract_methods(*args)
|
11
|
+
args.each do |name|
|
12
|
+
class_eval <<-END
|
13
|
+
def #{name}(*args)
|
14
|
+
errmsg = %Q(class \#{self.class.name} must implement abstract method #{self.name}##{name}().)
|
15
|
+
raise NotImplementedError.new(errmsg)
|
16
|
+
end
|
17
|
+
END
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end # module Abstract
|
22
|
+
end # module Qiniu
|
data/lib/qiniu/adt.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: sw=2 ts=2
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
|
6
|
+
module Qiniu
|
7
|
+
module ADT
|
8
|
+
|
9
|
+
class ApiSpecification
|
10
|
+
public
|
11
|
+
def to_str; return ""; end
|
12
|
+
end # class ApiSpecification
|
13
|
+
|
14
|
+
module Policy
|
15
|
+
public
|
16
|
+
def to_json
|
17
|
+
args = {}
|
18
|
+
|
19
|
+
self.params.each_pair do |key, fld|
|
20
|
+
val = self.__send__(key)
|
21
|
+
if !val.nil? then
|
22
|
+
args[fld] = val
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
return args.to_json
|
27
|
+
end # to_json
|
28
|
+
|
29
|
+
def to_query_string
|
30
|
+
args = []
|
31
|
+
|
32
|
+
self.params.each_pair do |key, fld|
|
33
|
+
val = self.__send__(key)
|
34
|
+
if !val.nil? then
|
35
|
+
new_fld = CGI.escape(fld.to_s)
|
36
|
+
new_val = CGI.escape(val.to_s).gsub('+', '%20')
|
37
|
+
args.push("#{new_fld}=#{new_val}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
return args.join("&")
|
42
|
+
end # to_query_string
|
43
|
+
end # module Policy
|
44
|
+
|
45
|
+
end # module ADT
|
46
|
+
end # module Qiniu
|
data/lib/qiniu/auth.rb
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# vim: sw=2 ts=2
|
3
|
+
|
4
|
+
require 'hmac-sha1'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
require 'qiniu/exceptions'
|
8
|
+
|
9
|
+
module Qiniu
|
10
|
+
module Auth
|
11
|
+
DEFAULT_AUTH_SECONDS = 3600
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def calculate_deadline(expires_in, deadline = nil)
|
15
|
+
### 授权期计算
|
16
|
+
if expires_in.is_a?(Integer) && expires_in > 0 then
|
17
|
+
# 指定相对时间,单位:秒
|
18
|
+
return Time.now.to_i + expires_in
|
19
|
+
elsif deadline.is_a?(Integer) then
|
20
|
+
# 指定绝对时间,常用于调试和单元测试
|
21
|
+
return deadline
|
22
|
+
end
|
23
|
+
|
24
|
+
# 默认授权期1小时
|
25
|
+
return Time.now.to_i + DEFAULT_AUTH_SECONDS
|
26
|
+
end # calculate_deadline
|
27
|
+
end # class << self
|
28
|
+
|
29
|
+
class PutPolicy
|
30
|
+
private
|
31
|
+
def initialize(bucket,
|
32
|
+
key = nil,
|
33
|
+
expires_in = DEFAULT_AUTH_SECONDS,
|
34
|
+
deadline = nil)
|
35
|
+
### 设定scope参数(必填项目)
|
36
|
+
self.scope!(bucket, key)
|
37
|
+
|
38
|
+
### 设定deadline参数(必填项目)
|
39
|
+
@expires_in = expires_in
|
40
|
+
@deadline = Auth.calculate_deadline(expires_in, deadline)
|
41
|
+
end # initialize
|
42
|
+
|
43
|
+
PARAMS = {
|
44
|
+
# 字符串类型参数
|
45
|
+
:scope => "scope" ,
|
46
|
+
:save_key => "saveKey" ,
|
47
|
+
:end_user => "endUser" ,
|
48
|
+
:return_url => "returnUrl" ,
|
49
|
+
:return_body => "returnBody" ,
|
50
|
+
:callback_url => "callbackUrl" ,
|
51
|
+
:callback_body => "callbackBody" ,
|
52
|
+
:persistent_ops => "persistentOps" ,
|
53
|
+
:persistent_notify_url => "persistentNotifyUrl" ,
|
54
|
+
:persistent_pipeline => "persistentPipeline" ,
|
55
|
+
|
56
|
+
# 数值类型参数
|
57
|
+
:deadline => "deadline" ,
|
58
|
+
:insert_only => "insertOnly" ,
|
59
|
+
:fsize_limit => "fsizeLimit" ,
|
60
|
+
:detect_mime => "detectMime" ,
|
61
|
+
:mime_limit => "mimeLimit"
|
62
|
+
} # PARAMS
|
63
|
+
|
64
|
+
public
|
65
|
+
attr_reader :bucket, :key
|
66
|
+
|
67
|
+
def scope!(bucket, key = nil)
|
68
|
+
@bucket = bucket
|
69
|
+
@key = key
|
70
|
+
|
71
|
+
if key.nil? then
|
72
|
+
# 新增语义,文件已存在则失败
|
73
|
+
@scope = bucket
|
74
|
+
else
|
75
|
+
# 覆盖语义,文件已存在则直接覆盖
|
76
|
+
@scope = "#{bucket}:#{key}"
|
77
|
+
end
|
78
|
+
end # scope!
|
79
|
+
|
80
|
+
def expires_in!(seconds)
|
81
|
+
if !seconds.nil? then
|
82
|
+
return @expires_in
|
83
|
+
end
|
84
|
+
|
85
|
+
@epires_in = seconds
|
86
|
+
@deadline = Auth.calculate_deadline(seconds)
|
87
|
+
|
88
|
+
return @expires_in
|
89
|
+
end # expires_in!
|
90
|
+
|
91
|
+
def expires_in=(seconds)
|
92
|
+
return expires_in!(seconds)
|
93
|
+
end # expires_in=
|
94
|
+
|
95
|
+
def expires_in
|
96
|
+
return @expires_in
|
97
|
+
end # expires_in
|
98
|
+
|
99
|
+
def allow_mime_list! (list)
|
100
|
+
@mime_limit = list
|
101
|
+
end # allow_mime_list!
|
102
|
+
|
103
|
+
def deny_mime_list! (list)
|
104
|
+
@mime_limit = "!#{list}"
|
105
|
+
end # deny_mime_list!
|
106
|
+
|
107
|
+
def insert_only!
|
108
|
+
@insert_only = 1
|
109
|
+
end # insert_only!
|
110
|
+
|
111
|
+
def detect_mime!
|
112
|
+
@detect_mime = 1
|
113
|
+
end # detect_mime!
|
114
|
+
|
115
|
+
def to_json
|
116
|
+
args = {}
|
117
|
+
|
118
|
+
PARAMS.each_pair do |key, fld|
|
119
|
+
val = self.__send__(key)
|
120
|
+
if !val.nil? then
|
121
|
+
args[fld] = val
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
return args.to_json
|
126
|
+
end # to_json
|
127
|
+
|
128
|
+
PARAMS.each_pair do |key, fld|
|
129
|
+
attr_accessor key
|
130
|
+
end
|
131
|
+
end # class PutPolicy
|
132
|
+
|
133
|
+
class << self
|
134
|
+
EMPTY_ARGS = {}
|
135
|
+
|
136
|
+
### 生成下载授权URL
|
137
|
+
def authorize_download_url(url, args = EMPTY_ARGS)
|
138
|
+
### 提取AK/SK信息
|
139
|
+
access_key = Config.settings[:access_key]
|
140
|
+
secret_key = Config.settings[:secret_key]
|
141
|
+
|
142
|
+
download_url = url
|
143
|
+
|
144
|
+
### URL变换:追加FOP指令
|
145
|
+
if args[:fop].is_a?(String) && args[:fop] != '' then
|
146
|
+
if download_url.index('?').is_a?(Fixnum) then
|
147
|
+
# 已有参数
|
148
|
+
download_url = "#{download_url}&#{args[:fop]}"
|
149
|
+
else
|
150
|
+
# 尚无参数
|
151
|
+
download_url = "#{download_url}?#{args[:fop]}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
### 授权期计算
|
156
|
+
e = Auth.calculate_deadline(args[:expires_in], args[:deadline])
|
157
|
+
|
158
|
+
### URL变换:追加授权期参数
|
159
|
+
if download_url.index('?').is_a?(Fixnum) then
|
160
|
+
# 已有参数
|
161
|
+
download_url = "#{download_url}&e=#{e}"
|
162
|
+
else
|
163
|
+
# 尚无参数
|
164
|
+
download_url = "#{download_url}?e=#{e}"
|
165
|
+
end
|
166
|
+
|
167
|
+
### 生成数字签名
|
168
|
+
sign = HMAC::SHA1.new(secret_key).update(download_url).digest
|
169
|
+
encoded_sign = Utils.urlsafe_base64_encode(sign)
|
170
|
+
|
171
|
+
### 生成下载授权凭证
|
172
|
+
dntoken = "#{access_key}:#{encoded_sign}"
|
173
|
+
|
174
|
+
### 返回下载授权URL
|
175
|
+
return "#{download_url}&token=#{dntoken}"
|
176
|
+
end # authorize_download_url
|
177
|
+
|
178
|
+
def generate_acctoken(url, body = '')
|
179
|
+
### 提取AK/SK信息
|
180
|
+
access_key = Config.settings[:access_key]
|
181
|
+
secret_key = Config.settings[:secret_key]
|
182
|
+
|
183
|
+
### 解析URL,生成待签名字符串
|
184
|
+
uri = URI.parse(url)
|
185
|
+
signing_str = uri.path
|
186
|
+
|
187
|
+
# 如有QueryString部分,则需要加上
|
188
|
+
query_string = uri.query
|
189
|
+
if query_string.is_a?(String) && !query_string.empty?
|
190
|
+
signing_str += '?' + query_string
|
191
|
+
end
|
192
|
+
|
193
|
+
# 追加换行符
|
194
|
+
signing_str += "\n"
|
195
|
+
|
196
|
+
# 如果有Body,则也加上
|
197
|
+
# (仅限于mime == "application/x-www-form-urlencoded"的情况)
|
198
|
+
if body.is_a?(String) && !body.empty?
|
199
|
+
signing_str += body
|
200
|
+
end
|
201
|
+
|
202
|
+
### 生成数字签名
|
203
|
+
sign = HMAC::SHA1.new(secret_key).update(signing_str).digest
|
204
|
+
encoded_sign = Utils.urlsafe_base64_encode(sign)
|
205
|
+
|
206
|
+
### 生成管理授权凭证
|
207
|
+
acctoken = "#{access_key}:#{encoded_sign}"
|
208
|
+
|
209
|
+
### 返回管理授权凭证
|
210
|
+
return acctoken
|
211
|
+
end # generate_acctoken
|
212
|
+
|
213
|
+
def generate_uptoken(put_policy)
|
214
|
+
### 提取AK/SK信息
|
215
|
+
access_key = Config.settings[:access_key]
|
216
|
+
secret_key = Config.settings[:secret_key]
|
217
|
+
|
218
|
+
### 生成待签名字符串
|
219
|
+
encoded_put_policy = Utils.urlsafe_base64_encode(put_policy.to_json)
|
220
|
+
|
221
|
+
### 生成数字签名
|
222
|
+
sign = HMAC::SHA1.new(secret_key).update(encoded_put_policy).digest
|
223
|
+
encoded_sign = Utils.urlsafe_base64_encode(sign)
|
224
|
+
|
225
|
+
### 生成上传授权凭证
|
226
|
+
uptoken = "#{access_key}:#{encoded_sign}:#{encoded_put_policy}"
|
227
|
+
|
228
|
+
### 返回上传授权凭证
|
229
|
+
return uptoken
|
230
|
+
end # generate_uptoken
|
231
|
+
end # class << self
|
232
|
+
|
233
|
+
end # module Auth
|
234
|
+
end # module Qiniu
|