#coding=utf-8 # # ucloud 文件上传 # require 'base64' require 'openssl' require 'faraday' module Educoder class Ufile PATH_PREFIX = %r{^/} def initialize(uploader={}) @ucloud_public_key = uploader[:ucloud_public_key] @ucloud_private_key = uploader[:ucloud_private_key] @ucloud_public_read = uploader[:ucloud_public_read] @ucloud_bucket = @ucloud_public_read ? uploader[:ucloud_public_bucket] : uploader[:ucloud_private_bucket] @ucloud_bucket_host = @ucloud_public_read ? uploader[:ucloud_public_bucket_host] : uploader[:ucloud_private_bucket_host] @ucloud_cdn_host = @ucloud_public_read ? uploader[:ucloud_public_cdn_host] : uploader[:ucloud_private_cdn_host] @ucloud_private_expire_seconds = uploader[:ucloud_private_expire_seconds] || 300 unless @ucloud_cdn_host.include?('//') raise "config.ucloud_cdn_host requirement include // http:// or https://, but you give: #{@ucloud_cdn_host}" end end # 上传文件 def put(path, file, headers = {}) path.sub!(PATH_PREFIX, '') response = conn.put(path, file.read) do |req| req.headers = headers token = authorization(req.method, headers['Content-Type'], path) req.headers['Authorization'] = token end if response.success? true else raise 'Ucloud上传失败' end end # 读取文件 def get(path) path.sub!(PATH_PREFIX, '') response = conn.get(url(path)) if response.success? return response else raise 'Ucloud Get File Fail' end end # 删除文件 def delete(path) path.sub!(PATH_PREFIX, '') response = conn.delete(url(path)) do |req| req.headers['Authorization'] = authorization(req.method, nil, path) end if response.success? true else raise 'Ucloud Get File Fail' end end def url(path) if @ucloud_public_read public_get_url(path) else private_get_url(path) end end # 公开的访问地址 def public_get_url(path) path.sub!(PATH_PREFIX, '') [@ucloud_cdn_host, path].join('/') end # 私有空间访问地址 def private_get_url(path) public_get_url(path) + privite_get_url_auth(path) end private def conn @conn ||= begin Faraday.new(url: @ucloud_bucket_host) do |req| req.request :url_encoded req.adapter Faraday.default_adapter end end end # 私密查看url的认证信息 def privite_get_url_auth(path) expired_ts = private_expire_ts signed_str = signature(string_to_sign('GET', nil, path, expired_ts)) "?UCloudPublicKey=#{@ucloud_public_key}&Expires=#{expired_ts}&Signature=#{signed_str}" end def private_expire_ts @ucloud_private_expire_seconds + Time.now.to_i end def authorization(http_method, content_type, path) signed_str = signature(string_to_sign(http_method, content_type, path)) "UCloud " + @ucloud_public_key + ":" + signed_str end def signature(str) Base64.strict_encode64(OpenSSL::HMAC.digest('sha1', @ucloud_private_key, str)) end def string_to_sign(http_method, ori_content_type, path, expired_ts = nil) http_verb = "#{http_method.upcase}\n" content_md5 = "\n" content_type = "#{ori_content_type}\n" timestamp = "#{expired_ts}\n" full_path = "/#{@ucloud_bucket}/#{path}" http_verb + content_md5 + content_type + timestamp + full_path end end end