Class: CarrierWave::Storage::Fog::File

Inherits:
Object
  • Object
show all
Includes:
Utilities::FileName, Utilities::Uri
Defined in:
lib/carrierwave/storage/fog.rb

Constant Summary collapse

DEFAULT_S3_REGION =
'us-east-1'.freeze

Constants included from Utilities::Uri

Utilities::Uri::NON_ASCII, Utilities::Uri::PATH_SAFE, Utilities::Uri::PATH_UNSAFE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utilities::FileName

#basename, #extension

Constructor Details

#initialize(uploader, base, path) ⇒ File

Returns a new instance of File.



279
280
281
# File 'lib/carrierwave/storage/fog.rb', line 279

def initialize(uploader, base, path)
  @uploader, @base, @path, @content_type = uploader, base, path, nil
end

Instance Attribute Details

#pathObject (readonly)

Current local path to file

Returns

String

a path to file



179
180
181
# File 'lib/carrierwave/storage/fog.rb', line 179

def path
  @path
end

Instance Method Details

#attributesObject

Return all attributes from file

Returns

Hash

attributes from file



188
189
190
# File 'lib/carrierwave/storage/fog.rb', line 188

def attributes
  file.attributes
end

#authenticated_url(options = {}) ⇒ Object

Return a temporary authenticated url to a private file, if available Only supported for AWS, Rackspace, Google, AzureRM and Aliyun providers

Returns

String

temporary authenticated url

or
NilClass

no authenticated url available



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/carrierwave/storage/fog.rb', line 202

def authenticated_url(options = {})
  if ['AWS', 'Google', 'Rackspace', 'OpenStack', 'AzureRM', 'Aliyun', 'backblaze'].include?(fog_provider)
    # avoid a get by using local references
    local_directory = connection.directories.new(:key => @uploader.fog_directory)
    local_file = local_directory.files.new(:key => path)
    expire_at = options[:expire_at] || ::Fog::Time.now.since(@uploader.fog_authenticated_url_expiration.to_i)
    case fog_provider
    when 'AWS', 'Google'
      # Older versions of fog-google do not support options as a parameter
      if url_options_supported?(local_file)
        local_file.url(expire_at, options)
      else
        warn "Options hash not supported in #{local_file.class}. You may need to upgrade your Fog provider."
        local_file.url(expire_at)
      end
    when 'Rackspace', 'OpenStack'
      connection.get_object_https_url(@uploader.fog_directory, path, expire_at, options)
    when 'Aliyun'
      expire_at -= Time.now
      local_file.url(expire_at)
    else
      local_file.url(expire_at)
    end
  end
end

#content_typeObject

Lookup value for file content-type header

Returns

String

value of content-type



235
236
237
# File 'lib/carrierwave/storage/fog.rb', line 235

def content_type
  @content_type || file.try(:content_type)
end

#content_type=(new_content_type) ⇒ Object

Set non-default content-type header (default is file.content_type)

Returns

String

returns new content type value



246
247
248
# File 'lib/carrierwave/storage/fog.rb', line 246

def content_type=(new_content_type)
  @content_type = new_content_type
end

#copy_to(new_path) ⇒ CarrierWave::Storage::Fog::File

Creates a copy of this file and returns it.

Parameters

new_path (String)

The path where the file should be copied to.

Returns

Returns:



456
457
458
459
# File 'lib/carrierwave/storage/fog.rb', line 456

def copy_to(new_path)
  file.copy(@uploader.fog_directory, new_path, copy_options)
  CarrierWave::Storage::Fog::File.new(@uploader, @base, new_path)
end

#deleteObject

Remove the file from service

Returns

Boolean

true for success or raises error



257
258
259
260
261
262
# File 'lib/carrierwave/storage/fog.rb', line 257

def delete
  # avoid a get by just using local reference
  directory.files.new(:key => path).destroy.tap do |result|
    @file = nil if result
  end
end

#empty?Boolean

Returns

Boolean

whether the file is non-existent or empty

Returns:

  • (Boolean)


319
320
321
# File 'lib/carrierwave/storage/fog.rb', line 319

def empty?
  !exists? || size.zero?
end

#exists?Boolean

Check if the file exists on the remote service

Returns

Boolean

true if file exists or false

Returns:

  • (Boolean)


329
330
331
# File 'lib/carrierwave/storage/fog.rb', line 329

def exists?
  !!file
end

#filename(options = {}) ⇒ Object

Return file name, if available

Returns

String

file name

or
NilClass

no file name available



440
441
442
443
# File 'lib/carrierwave/storage/fog.rb', line 440

def filename(options = {})
  return unless (file_url = url(options))
  CGI.unescape(file_url.split('?').first).gsub(/.*\/(.*?$)/, '\1')
end

#headersObject

deprecated: All attributes from file (includes headers)

Returns

Hash

attributes from file



271
272
273
274
275
276
277
# File 'lib/carrierwave/storage/fog.rb', line 271

def headers
  location = caller.first
  warning = "[yellow][WARN] headers is deprecated, use attributes instead[/]"
  warning << " [light_black](#{location})[/]"
  Formatador.display_line(warning)
  attributes
end

#public_urlObject

Return a url to a public file, if available

Returns

String

public url

or
NilClass

no public url available



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/carrierwave/storage/fog.rb', line 365

def public_url
  encoded_path = encode_path(path)
  if (host = @uploader.asset_host)
    if host.respond_to? :call
      "#{host.call(self)}/#{encoded_path}"
    else
      "#{host}/#{encoded_path}"
    end
  else
    # AWS/Google optimized for speed over correctness
    case fog_provider
    when 'AWS'
      # check if some endpoint is set in fog_credentials
      if @uploader.fog_credentials.has_key?(:endpoint)
        raise 'fog_aws_fips = true is incompatible with :endpoint, as FIPS endpoints do not support path-style URLs.' if @uploader.fog_aws_fips
        "#{@uploader.fog_credentials[:endpoint]}/#{@uploader.fog_directory}/#{encoded_path}"
      else
        protocol = @uploader.fog_use_ssl_for_aws ? "https" : "http"

        subdomain_regex = /^(?:[a-z]|\d(?!\d{0,2}(?:\d{1,3}){3}$))(?:[a-z0-9\.]|(?![\-])|\-(?![\.])){1,61}[a-z0-9]$/
        # To use the virtual-hosted style, the bucket name needs to be representable as a subdomain
        use_virtual_hosted_style = @uploader.fog_directory.to_s =~ subdomain_regex && !(protocol == 'https' && @uploader.fog_directory =~ /\./)

        region = @uploader.fog_credentials[:region].to_s
        regional_host = 's3.amazonaws.com' # used for DEFAULT_S3_REGION or no region set
        if @uploader.fog_aws_fips
          regional_host = "s3-fips.#{region}.amazonaws.com" # https://aws.amazon.com/compliance/fips/
        elsif ![DEFAULT_S3_REGION, ''].include?(region)
          regional_host = "s3.#{region}.amazonaws.com"
        end

        if use_virtual_hosted_style
          regional_host = 's3-accelerate.amazonaws.com' if @uploader.fog_aws_accelerate
          "#{protocol}://#{@uploader.fog_directory}.#{regional_host}/#{encoded_path}"
        else # directory is not a valid subdomain, so use path style for access
          raise 'FIPS Endpoints can only be used with Virtual Hosted-Style addressing.' if @uploader.fog_aws_fips
          "#{protocol}://#{regional_host}/#{@uploader.fog_directory}/#{encoded_path}"
        end
      end
    when 'Google'
      # https://cloud.google.com/storage/docs/access-public-data
      "https://storage.googleapis.com/#{@uploader.fog_directory}/#{encoded_path}"
    else
      # avoid a get by just using local reference
      directory.files.new(:key => path).public_url
    end
  end
end

#readObject

Read content of file from service

Returns

String

contents of file



289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/carrierwave/storage/fog.rb', line 289

def read
  file_body = file&.body

  return if file_body.nil?
  return file_body unless file_body.is_a?(::File)

  # Fog::Storage::XXX::File#body could return the source file which was uploaded to the remote server.
  return read_source_file if ::File.exist?(file_body.path)

  # If the source file doesn't exist, the remote content is read
  @file = nil
  file.body
end

#sizeObject

Return size of file body

Returns

Integer

size of file body



310
311
312
# File 'lib/carrierwave/storage/fog.rb', line 310

def size
  file.nil? ? 0 : file.content_length
end

#store(new_file) ⇒ Object

Write file to service

Returns

Boolean

true on success or raises error



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/carrierwave/storage/fog.rb', line 339

def store(new_file)
  if new_file.is_a?(self.class)
    new_file.copy_to(path)
  else
    fog_file = new_file.to_file
    @content_type ||= new_file.content_type
    @file = directory.files.create({
      :body         => fog_file || new_file.read,
      :content_type => @content_type,
      :key          => path,
      :public       => @uploader.fog_public
    }.merge(@uploader.fog_attributes))
    fog_file.close if fog_file && !fog_file.closed?
  end
  true
end

#to_fileObject

Return the local file

Returns

File

The local file as Ruby’s File class

or
NilClass

When there’s no file, or the file is remotely stored



470
471
472
473
474
475
476
477
478
# File 'lib/carrierwave/storage/fog.rb', line 470

def to_file
  return nil unless file.body.is_a? ::File

  if file.body.closed?
    ::File.open(file.body.path) # Reopen if it's already closed
  else
    file.body
  end
end

#url(options = {}) ⇒ Object

Return url to file, if available

Returns

String

url

or
NilClass

no url available



423
424
425
426
427
428
429
# File 'lib/carrierwave/storage/fog.rb', line 423

def url(options = {})
  if !@uploader.fog_public
    authenticated_url(options)
  else
    public_url
  end
end