class ActiveStorage::Service::AliyunService

Attributes

config[R]

Public Class Methods

new(**config) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 6
def initialize(**config)
  Aliyun::Common::Logging.set_log_file("/dev/null")
  @config = config
end

Public Instance Methods

delete(key) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 43
def delete(key)
  instrument :delete, key: key do
    bucket.delete_object(path_for(key))
  end
end
delete_prefixed(prefix) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 49
def delete_prefixed(prefix)
  instrument :delete_prefixed, prefix: prefix do
    files = bucket.list_objects(prefix: path_for(prefix))
    return if files.blank?
    keys = files.map(&:key)
    return if keys.blank?
    bucket.batch_delete_objects(keys, quiet: true)
  end
end
download(key) { |chunk| ... } click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 19
def download(key)
  instrument :download, key: key do
    chunk_buff = []
    bucket.get_object(path_for(key)) do |chunk|
      if block_given?
        yield chunk
      else
        chunk_buff << chunk
      end
    end
    chunk_buff.join("")
  end
end
download_chunk(key, range) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 33
def download_chunk(key, range)
  instrument :download_chunk, key: key, range: range do
    uri = URI(url(key, expires_in: 30.seconds, filename: ActiveStorage::Filename.new(""), content_type: "application/octet-stream", disposition: "inline"))

    Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |client|
      client.get(uri, "Range" => "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body
    end
  end
end
exist?(key) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 59
def exist?(key)
  instrument :exist, key: key do |payload|
    bucket.object_exists?(path_for(key))
  end
end
headers_for_direct_upload(key, content_type:, checksum:, **) click to toggle source

Headers for Direct Upload help.aliyun.com/document_detail/31951.html headers is required use x-oss-date instead

# File lib/active_storage/service/aliyun_service.rb, line 102
def headers_for_direct_upload(key, content_type:, checksum:, **)
  date = Time.now.httpdate
  {
    "Content-Type" => content_type,
    "Content-MD5" => checksum,
    "Authorization" => authorization(key, content_type, checksum, date),
    "x-oss-date" => date,
  }
end
upload(key, io, checksum: nil) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 11
def upload(key, io, checksum: nil)
  instrument :upload, key: key, checksum: checksum do
    bucket.put_object(path_for(key)) do |stream|
      stream << io.read
    end
  end
end
url(key, expires_in:, filename: nil, content_type:, disposition:, params: {}) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 65
def url(key, expires_in:, filename: nil, content_type:, disposition:, params: {})
  instrument :url, key: key do |payload|
    sign    = private_mode? || disposition == :attachment
    filekey = path_for(key)

    if disposition == :attachment
      params["response-content-type"] = content_type if content_type
      unless filename.is_a?(ActiveStorage::Filename)
        filename = ActiveStorage::Filename.new(filename)
      end

      params["response-content-disposition"] = content_disposition_with(type: disposition, filename: filename)
    end

    generated_url = object_url(filekey, sign: sign, expires_in: expires_in, params: params)
    payload[:url] = generated_url
    generated_url
  end
end
url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:) click to toggle source

You must setup CORS on OSS control panel to allow JavaScript request from your site domain. www.alibabacloud.com/help/zh/doc-detail/31988.htm help.aliyun.com/document_detail/31925.html Source: *.your.host.com Allowed Methods: POST, PUT, HEAD Allowed Headers: *

# File lib/active_storage/service/aliyun_service.rb, line 91
def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:)
  instrument :url, key: key do |payload|
    generated_url = bucket.object_url(path_for(key), false)
    payload[:url] = generated_url
    generated_url
  end
end

Private Instance Methods

authorization(key, content_type, checksum, date) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 156
def authorization(key, content_type, checksum, date)
  filename = File.expand_path("/#{bucket.name}/#{path_for(key)}")
  addition_headers = "x-oss-date:#{date}"
  sign = ["PUT", checksum, content_type, date, addition_headers, filename].join("\n")
  signature = bucket.sign(sign)
  "OSS " + config.fetch(:access_key_id) + ":" + signature
end
bucket() click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 145
def bucket
  return @bucket if defined? @bucket
  @bucket = client.get_bucket(config.fetch(:bucket))
  @bucket
end
client() click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 168
def client
  @client ||= Aliyun::OSS::Client.new(
    endpoint: endpoint,
    access_key_id: config.fetch(:access_key_id),
    access_key_secret: config.fetch(:access_key_secret),
    cname: config.fetch(:cname, false)
  )
end
endpoint() click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 164
def endpoint
  config.fetch(:endpoint, "https://oss-cn-hangzhou.aliyuncs.com")
end
object_url(key, sign:, expires_in: 60, params: {}) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 120
def object_url(key, sign:, expires_in: 60, params: {})
  url = bucket.object_url(key, false)
  unless sign
    return url if params.blank?
    return url + "?" + params.to_query
  end

  resource = "/#{bucket.name}/#{key}"
  expires  = Time.now.to_i + expires_in
  query    = {
    "Expires" => expires,
    "OSSAccessKeyId" => config.fetch(:access_key_id)
  }
  query.merge!(params)

  if params.present?
    resource += "?" + params.map { |k, v| "#{k}=#{v}" }.sort.join("&")
  end

  string_to_sign = ["GET", "", "", expires, resource].join("\n")
  query["Signature"] = bucket.sign(string_to_sign)

  [url, query.to_query].join('?')
end
path_for(key) click to toggle source
# File lib/active_storage/service/aliyun_service.rb, line 115
def path_for(key)
  return key unless config.fetch(:path, nil)
  File.join(config.fetch(:path), key)
end
private_mode?() click to toggle source

Bucket mode :public | :private

# File lib/active_storage/service/aliyun_service.rb, line 152
def private_mode?
  @private_mode ||= config.fetch(:mode, "public").to_s == "private"
end