qiniu_jxb 6.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +9 -0
  4. data/CHANGELOG.md +118 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +37 -0
  7. data/LICENSE +22 -0
  8. data/README.md +47 -0
  9. data/Rakefile +21 -0
  10. data/docs/README.md +790 -0
  11. data/lib/qiniu-rs.rb +2 -0
  12. data/lib/qiniu.rb +209 -0
  13. data/lib/qiniu/abstract.rb +22 -0
  14. data/lib/qiniu/adt.rb +46 -0
  15. data/lib/qiniu/auth.rb +234 -0
  16. data/lib/qiniu/config.rb +58 -0
  17. data/lib/qiniu/exceptions.rb +120 -0
  18. data/lib/qiniu/fop.rb +4 -0
  19. data/lib/qiniu/http.rb +137 -0
  20. data/lib/qiniu/image.rb +38 -0
  21. data/lib/qiniu/log.rb +15 -0
  22. data/lib/qiniu/management.rb +128 -0
  23. data/lib/qiniu/misc.rb +33 -0
  24. data/lib/qiniu/pfop.rb +124 -0
  25. data/lib/qiniu/resumable_upload.rb +319 -0
  26. data/lib/qiniu/storage.rb +5 -0
  27. data/lib/qiniu/tokens/access_token.rb +21 -0
  28. data/lib/qiniu/tokens/download_token.rb +31 -0
  29. data/lib/qiniu/tokens/qbox_token.rb +38 -0
  30. data/lib/qiniu/tokens/upload_token.rb +47 -0
  31. data/lib/qiniu/upload.rb +138 -0
  32. data/lib/qiniu/utils.rb +109 -0
  33. data/lib/qiniu/version.rb +17 -0
  34. data/qiniu.gemspec +29 -0
  35. data/spec/qiniu/abstract_spec.rb +30 -0
  36. data/spec/qiniu/auth_spec.rb +81 -0
  37. data/spec/qiniu/image_logo_for_test.png +0 -0
  38. data/spec/qiniu/image_spec.rb +89 -0
  39. data/spec/qiniu/management_spec.rb +156 -0
  40. data/spec/qiniu/misc_spec.rb +59 -0
  41. data/spec/qiniu/pfop_spec.rb +89 -0
  42. data/spec/qiniu/qiniu_spec.rb +329 -0
  43. data/spec/qiniu/tokens/qbox_token_spec.rb +29 -0
  44. data/spec/qiniu/upload_spec.rb +308 -0
  45. data/spec/qiniu/utils_spec.rb +49 -0
  46. data/spec/qiniu/version_spec.rb +10 -0
  47. data/spec/spec_helper.rb +19 -0
  48. metadata +220 -0
data/lib/qiniu-rs.rb ADDED
@@ -0,0 +1,2 @@
1
+ # More logical way to require 'qiniu-rs'
2
+ require File.join(File.dirname(__FILE__), 'qiniu', 'qiniu')
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