为简单起见,在实践单文件直传过程中,将尽量使用编程语言的自带函数,避免过度依赖第三方组件;同时为讲解原理,也不会直接使用七牛官方Ruby-SDK,有需要的读者可以自行研究。
■ 签发上传授权凭证
#!/usr/bin/env ruby
# encoding : utf-8
# upload_token.rb
require 'json'
require 'base64'
require 'openssl'
# 根据传入参数,构造一个上传策略
def put_policy(bucket, expires)
# 生成一个Hash对象
put_policy = Hash.new()
# 仅指定目标存储空间,即“新增资源”语意:
# 资源不存在则创建
# 资源已存在,且与上传内容不一致则失败
put_policy['scope'] = "#{bucket}"
# 计算授权有效期截止时间,UNIX时间戳格式
put_policy['deadline'] = (Time.now() + expires).tv_sec()
# 序列化为JSON字符串
return JSON.generate(put_policy)
end # put_policy
# 根据传入的上传策略,生成对应的上传授权凭证
def upload_token(access_key, secret_key, put_policy)
# 对上传策略做UrlSafe-Base64编码
encoded_put_policy = Base64.urlsafe_encode64(put_policy)
# 使用SHA1作为HASH函数,生成签名
sign = OpenSSL::HMAC.digest(
'sha1',
secret_key,
encoded_put_policy
)
# 对签名做UrlSafe-Base64编码
encoded_sign = Base64.urlsafe_encode64(sign)
# 拼出上传授权凭证,以“:”作为分隔符
return "#{access_key}:#{encoded_sign}:#{encoded_put_policy}"
end # upload_token
#### 以下部分为测试代码 ####
BUCKET = 'qiniu-ts-demo' # 使用时请更换成真实的存储空间名
EXPIRES = 3600
pp = put_policy(BUCKET, EXPIRES)
ACCESS_KEY = 'MY_ACCESS_KEY' # 使用时请更换成真实的AccessKey
SECRET_KEY = 'MY_SECRET_KEY' # 使用时请更换成真实的SecretKey
token = upload_token(ACCESS_KEY, SECRET_KEY, pp)
puts pp
# 输出示例:{"scope":"qiniu-ts-demo","deadline":1389772115}
puts token
# 输出示例:MY_ACCESS_KEY:rgAZqUhj2ojVsXhgol27ck9XmO8=:eyJzY29wZSI6InFpbml1LXRzLWRlbW8iLCJkZWFkbGluZSI6MTM4OTc3MjExNX0=
■ 上传文件
#!/usr/bin/env ruby
# encoding : utf-8
# put_file.rb
require 'json'
require 'net/http'
require './upload_token.rb'
BUCKET = 'qiniu-ts-demo' # 使用时请更换成真实的存储空间名
EXPIRES = 3600
ACCESS_KEY = 'MY_ACCESS_KEY' # 使用时请更换成真实的AccessKey
SECRET_KEY = 'MY_SECRET_KEY' # 使用时请更换成真实的SecretKey
# 生成上传授权凭证
upload_token = upload_token(
ACCESS_KEY,
SECRET_KEY,
put_policy(BUCKET, EXPIRES)
)
# 指定请求报文中的各个参数
file_name = 'test.txt'
file_content = <<TEXT
This is a test file for qiniu-ts-demo.
TEXT
boundary = 'a-string-never-exists-in-the-uploading-file'
# 生成请求报文体
req_body = <<HTTP_BODY
--#{boundary}
Content-Disposition: form-data; name="token"
#{upload_token}
--#{boundary}
Content-Disposition: form-data; name="file"; filename="#{file_name}"
#{file_content}
--#{boundary}--
HTTP_BODY
# 转换换行符
req_body.gsub!(/\n/, "\r\n")
# 生成Headers
req_headers = Hash.new()
req_headers['Host'] = "up.qiniu.com"
req_headers['Content-Type'] = "multipart/form-data; boundary=#{boundary}"
req_headers['Content-Length'] = "#{req_body.length}"
# 发送请求
http_client = Net::HTTP.new('up.qiniu.com', 80)
resp = http_client.post(
'/',
req_body,
req_headers
)
# 解析响应
puts "HTTP Code=#{resp.code}"
puts "HTTP Msg=#{resp.msg}"
puts "HTTP Body=#{resp.body()}"
# 输出示例:
# HTTP Code=200
# HTTP Msg=OK
# HTTP Body={"hash":"Ft4i6pVW8irlfIK_8KBHjSXA-4qM","key":"Ft4i6pVW8irlfIK_8KBHjSXA-4qM"}
200响应码表示上传成功,服务器返回资源内容的Hash值。因为上传时没有指定资源名,默认使用该Hash值作为资源名(Key)。
注意:在单文件直传接口中指定的FileName参数不会被当作资源名使用。
■ 验证上传结果
如何验证文件已经正确上传了呢?可以构造下载URL,通过浏览器验证。以上述Demo为例,根据下载URL构造规则:
http://<Bucket>.qiniudn.com/<Key>
可以得到对应的下载URL:
http://qiniu-ts-demo.qiniudn.com/Ft4i6pVW8irlfIK_8KBHjSXA-4qM
因为没有为资源指定MIME类型,浏览器会将资源作为二进制文件下载,可以使用文本编辑器来验证其内容。
■ 咱们行进到哪儿了?
通过简单的Ruby编程,正确地上传了一个文本文件,且可以通过浏览器下载该文件。
有了资源之后,可以进一步使用七牛云存储提供的丰富的文件云处理功能。这部分内容将在后续文章中介绍。
七牛云存储 © 2014 署名-非商业性使用-禁止演绎
允许自由转载,请注明作者及出处。