class S3::Object

Class responsible for handling objects stored in S3 buckets

Attributes

acl[R]
bucket[RW]
cache_control[RW]
content[W]
content_disposition[RW]
content_encoding[RW]
content_type[RW]
etag[R]
key[R]
last_modified[R]
metadata[R]
original_key[W]
size[RW]
storage_class[R]

Public Class Methods

new(bucket, options = {}) click to toggle source
# File lib/s3/object.rb, line 208
def initialize(bucket, options = {})
  @content_type = nil
  @content_encoding = nil
  @content_disposition = nil
  @cache_control = nil
  @acl = nil
  @last_modified = nil
  @etag = nil
  @size = nil
  @bucket = nil
  @key = nil
  @acl = nil
  @storage_class = nil
  @metadata = nil
  @content = nil

  self.bucket = bucket
  self.key = options[:key]
  self.last_modified = options[:last_modified]
  self.etag = options[:etag]
  self.size = options[:size]
  self.cache_control = options[:cache_control]
end

Public Instance Methods

==(other) click to toggle source

Compares the object with other object. Returns true if the key of the objects are the same, and both have the same buckets (see Bucket equality)

# File lib/s3/object.rb, line 19
def ==(other)
  other.equal?(self) || (other.instance_of?(self.class) && self.key == other.key && self.bucket == other.bucket)
end
acl=(acl) click to toggle source

Assigns a new ACL to the object. Please note that ACL is not retrieved from the server and set to “private” by default.

Example

object.acl = :public_read
# File lib/s3/object.rb, line 40
def acl=(acl)
  @acl = acl.to_s.gsub("_", "-") if acl
end
cname_url() click to toggle source

Returns Object's CNAME URL (without s3.amazonaws.com suffix) using protocol specified in Service, e.g. http://domain.com/key/with/path.extension. (you have to set the CNAME in your DNS before using the CNAME URL schema).

# File lib/s3/object.rb, line 140
def cname_url
  Addressable::URI.escape("#{protocol}#{name}/#{key}") if bucket.vhost?
end
content(reload = false) click to toggle source

Downloads the content of the object, and caches it. Pass true to clear the cache and download the object again.

# File lib/s3/object.rb, line 86
def content(reload = false)
  return @content unless reload or @content.nil?
  get_object
  @content
end
copy(options = {}) click to toggle source

Copies the file to another key and/or bucket.

Options

  • :key - New key to store object in

  • :bucket - New bucket to store object in (instance of S3::Bucket)

  • :acl - ACL of the copied object (default: “private”)

  • :content_type - Content type of the copied object (default: “application/octet-stream”)

# File lib/s3/object.rb, line 108
def copy(options = {})
  copy_object(options)
end
destroy() click to toggle source

Destroys the file on the server

# File lib/s3/object.rb, line 113
def destroy
  delete_object
  true
end
exists?() click to toggle source

Retrieves the object from the server, returns true if the object exists or false otherwise. Uses retrieve method, but catches S3::Error::NoSuchKey exception and returns false when it happens

# File lib/s3/object.rb, line 68
def exists?
  retrieve
  true
rescue Error::NoSuchKey
  false
end
full_key() click to toggle source

Returns full key of the object: e.g. bucket-name/object/key.ext

# File lib/s3/object.rb, line 24
def full_key
  [name, key].join("/")
end
key=(key) click to toggle source

Assigns a new key to the object, raises ArgumentError if given key is not valid key name

# File lib/s3/object.rb, line 30
def key=(key)
  raise ArgumentError.new("Invalid key name: #{key}") unless key_valid?(key)
  @key ||= key
end
request_acl() click to toggle source

Retrieves acl for object from the server.

Return: hash: user|group => permission

# File lib/s3/object.rb, line 79
def request_acl
  response = object_request(:get, :params => "acl")
  parse_acl(response.body)
end
retrieve() click to toggle source

Retrieves the object from the server. Method is used to download object information only (content type, size). Notice: It does NOT download the content of the object (use the content method to do it). Notice: this do not fetch acl information, use request_acl method for that.

# File lib/s3/object.rb, line 60
def retrieve
  object_headers
  self
end
save() click to toggle source

Saves the object, returns true if successfull.

# File lib/s3/object.rb, line 93
def save
  put_object
  true
end
storage_class=(storage_class) click to toggle source

Assigns a new storage class (RRS) to the object. Please note that the storage class is not retrieved from the server and set to “STANDARD” by default.

Example

object.storage_class = :reduced_redundancy
# File lib/s3/object.rb, line 50
def storage_class=(storage_class)
  @storage_class = storage_class.to_s.upcase if storage_class
end
temporary_url(expires_at = Time.now + 3600) click to toggle source

Returns a temporary url to the object that expires on the timestamp given. Defaults to one hour expire time.

# File lib/s3/object.rb, line 126
def temporary_url(expires_at = Time.now + 3600)
  signature = Signature.generate_temporary_url_signature(:bucket => name,
                                                         :resource => key,
                                                         :expires_at => expires_at,
                                                         :secret_access_key => secret_access_key)

  "#{url}?AWSAccessKeyId=#{self.bucket.service.access_key_id}&Expires=#{expires_at.to_i.to_s}&Signature=#{signature}"
end
url() click to toggle source

Returns Object's URL using protocol specified in service, e.g. http://domain.com.s3.amazonaws.com/key/with/path.extension

# File lib/s3/object.rb, line 120
def url
  "#{protocol}#{host}/#{path_prefix}#{Addressable::URI.escape(key)}"
end

Private Instance Methods

copy_object(options = {}) click to toggle source
# File lib/s3/object.rb, line 152
def copy_object(options = {})
  key = options[:key] or raise ArgumentError, "No key given"
  raise ArgumentError.new("Invalid key name: #{key}") unless key_valid?(key)
  bucket = options[:bucket] || self.bucket

  headers = {}

  headers[:x_amz_acl] = options[:acl] || acl || "private"
  headers[:content_type] = options[:content_type] || content_type || "application/octet-stream"
  headers[:content_encoding] = options[:content_encoding] if options[:content_encoding]
  headers[:content_disposition] = options[:content_disposition] if options[:content_disposition]
  headers[:cache_control] = options[:cache_control] if options[:cache_control]
  headers[:x_amz_copy_source] = full_key
  headers[:x_amz_metadata_directive] = options[:replace] == false ? "COPY" : "REPLACE"
  headers[:x_amz_copy_source_if_match] = options[:if_match] if options[:if_match]
  headers[:x_amz_copy_source_if_none_match] = options[:if_none_match] if options[:if_none_match]
  headers[:x_amz_copy_source_if_unmodified_since] = options[:if_modified_since] if options[:if_modified_since]
  headers[:x_amz_copy_source_if_modified_since] = options[:if_unmodified_since] if options[:if_unmodified_since]

  response = bucket.send(:bucket_request, :put, :path => key, :headers => headers)
  object_attributes = parse_copy_object_result(response.body)

  object = Object.send(:new, bucket, object_attributes.merge(:key => key, :size => size))
  object.acl = response["x-amz-acl"]
  object.content_type = response["content-type"]
  object.content_encoding = response["content-encoding"]
  object.content_disposition = response["content-disposition"]
  object.cache_control = response["cache-control"]
  object
end
delete_object(options = {}) click to toggle source
# File lib/s3/object.rb, line 204
def delete_object(options = {})
  object_request(:delete)
end
dump_headers() click to toggle source
# File lib/s3/object.rb, line 248
def dump_headers
  headers = {}
  headers[:x_amz_acl] = @acl || "private"
  headers[:x_amz_storage_class] = @storage_class || "STANDARD"
  headers[:content_type] = @content_type || "application/octet-stream"
  headers[:content_encoding] = @content_encoding if @content_encoding
  headers[:content_disposition] = @content_disposition if @content_disposition
  headers[:cache_control] = @cache_control if @cache_control
  headers
end
etag=(etag) click to toggle source
# File lib/s3/object.rb, line 240
def etag=(etag)
  @etag = etag[1..-2] if etag
end
get_object(options = {}) click to toggle source
# File lib/s3/object.rb, line 183
def get_object(options = {})
  response = object_request(:get, options)
  parse_headers(response)
end
key_valid?(key) click to toggle source
# File lib/s3/object.rb, line 244
def key_valid?(key)
  !(key.nil? or key.empty?)
end
last_modified=(last_modified) click to toggle source
# File lib/s3/object.rb, line 236
def last_modified=(last_modified)
  @last_modified = Time.parse(last_modified) if last_modified
end
object_headers(options = {}) click to toggle source
# File lib/s3/object.rb, line 188
def object_headers(options = {})
  response = object_request(:head, options)
  parse_headers(response)
rescue Error::ResponseError => e
  if e.response.code.to_i == 404
    raise Error::ResponseError.exception("NoSuchKey").new("The specified key does not exist.", nil)
  else
    raise e
  end
end
object_request(method, options = {}) click to toggle source
# File lib/s3/object.rb, line 232
def object_request(method, options = {})
  bucket.send(:bucket_request, method, options.merge(:path => key))
end
parse_headers(response) click to toggle source
# File lib/s3/object.rb, line 259
def parse_headers(response)
  @metadata = response.to_hash.select { |k, v| k.to_s.start_with?("x-amz-meta") }
  self.etag = response["etag"] if response.key?("etag")
  self.content_type = response["content-type"] if response.key?("content-type")
  self.content_disposition = response["content-disposition"] if response.key?("content-disposition")
  self.cache_control = response["cache-control"] if response.key?("cache-control")
  self.content_encoding = response["content-encoding"] if response.key?("content-encoding")
  self.last_modified = response["last-modified"] if response.key?("last-modified")
  if response.key?("content-range")
    self.size = response["content-range"].sub(/[^\/]+\//, "").to_i
  else
    self.size = response["content-length"]
    if body = response.body
      self.content = body
    end
  end
end
put_object() click to toggle source
# File lib/s3/object.rb, line 199
def put_object
  response = object_request(:put, :body => content, :headers => dump_headers)
  parse_headers(response)
end