class Marcel::MimeType

Constants

BINARY

Public Class Methods

extend(type, extensions: [], parents: [], magic: nil) click to toggle source
# File lib/marcel/mime_type.rb, line 8
def extend(type, extensions: [], parents: [], magic: nil)
  extensions = (Array(extensions) + Array(Marcel::TYPE_EXTS[type])).uniq
  parents = (Array(parents) + Array(Marcel::TYPE_PARENTS[type])).uniq
  Magic.add(type, extensions: extensions, magic: magic, parents: parents)
end
for(pathname_or_io = nil, name: nil, extension: nil, declared_type: nil) click to toggle source

Returns the most appropriate content type for the given file.

The first argument should be a Pathname or an IO. If it is a Pathname, the specified file will be opened first.

Optional parameters:

  • name: file name, if known

  • extension: file extension, if known

  • declared_type: MIME type, if known

The most appropriate type is determined by the following:

  • type declared by binary magic number data

  • type declared by the first of file name, file extension, or declared MIME type

If no type can be determined, then application/octet-stream is returned.

# File lib/marcel/mime_type.rb, line 29
def for(pathname_or_io = nil, name: nil, extension: nil, declared_type: nil)
  filename_type = for_name(name) || for_extension(extension)
  most_specific_type for_data(pathname_or_io), for_declared_type(declared_type), filename_type, BINARY
end

Private Class Methods

for_data(pathname_or_io) click to toggle source
# File lib/marcel/mime_type.rb, line 36
def for_data(pathname_or_io)
  if pathname_or_io
    with_io(pathname_or_io) do |io|
      if magic = Marcel::Magic.by_magic(io)
        magic.type.downcase
      end
    end
  end
end
for_declared_type(declared_type) click to toggle source
# File lib/marcel/mime_type.rb, line 62
def for_declared_type(declared_type)
  type = parse_media_type(declared_type)

  # application/octet-stream is treated as an undeclared/missing type,
  # allowing the type to be inferred from the filename. If there's no
  # filename extension, then the type falls back to binary anyway.
  type unless type == BINARY
end
for_extension(extension) click to toggle source
# File lib/marcel/mime_type.rb, line 54
def for_extension(extension)
  if extension
    if magic = Marcel::Magic.by_extension(extension)
      magic.type.downcase
    end
  end
end
for_name(name) click to toggle source
# File lib/marcel/mime_type.rb, line 46
def for_name(name)
  if name
    if magic = Marcel::Magic.by_path(name)
      magic.type.downcase
    end
  end
end
most_specific_type(*candidates) click to toggle source

For some document types (notably Microsoft Office) we recognise the main content type with magic, but not the specific subclass. In this situation, if we can get a more specific class using either the name or declared_type, we should use that in preference

# File lib/marcel/mime_type.rb, line 89
def most_specific_type(*candidates)
  candidates.compact.uniq.reduce do |type, candidate|
    Marcel::Magic.child?(candidate, type) ? candidate : type
  end
end
parse_media_type(content_type) click to toggle source
# File lib/marcel/mime_type.rb, line 79
def parse_media_type(content_type)
  if content_type
    result = content_type.downcase.split(/[;,\s]/, 2).first
    result if result && result.index("/")
  end
end
with_io(pathname_or_io) { |pathname_or_io| ... } click to toggle source
# File lib/marcel/mime_type.rb, line 71
def with_io(pathname_or_io, &block)
  if defined?(Pathname) && pathname_or_io.is_a?(Pathname)
    pathname_or_io.open(&block)
  else
    yield pathname_or_io
  end
end