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-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
|