130 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
#coding=utf-8
 | 
						|
#
 | 
						|
# ucloud 文件上传
 | 
						|
#
 | 
						|
 | 
						|
require 'base64'
 | 
						|
require 'openssl'
 | 
						|
require 'faraday'
 | 
						|
 | 
						|
module Gitlink
 | 
						|
  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 |