Commit f407412f by Jon Yurek

Adds a class for managing content type detection

parent 0eae7dbe
......@@ -40,6 +40,7 @@ require 'paperclip/attachment'
require 'paperclip/attachment_options'
require 'paperclip/storage'
require 'paperclip/callbacks'
require 'paperclip/content_type_detector'
require 'paperclip/glue'
require 'paperclip/errors'
require 'paperclip/missing_attachment_styles'
......
module Paperclip
class ContentTypeDetector
def initialize(filename)
@filename = filename
end
def detect
if !match?
type_from_file_command
elsif !multiple?
possible_types.first
else
best_type_match
end.to_s
end
private
def possible_types
@possible_types ||= MIME::Types.type_for(@filename)
end
def match?
possible_types.length > 0
end
def multiple?
possible_types.length > 1
end
def best_type_match
official_types = possible_types.reject {|type| type.content_type.match(/\/x-/) }
(official_types.first || possible_types.first).content_type
end
def type_from_file_command
# On BSDs, `file` doesn't give a result code of 1 if the file doesn't exist.
type = Paperclip.run("file", "-b --mime :file", :file => @filename)
if type.match(/\(.*?\)/)
type = "application/octet-stream"
end
type.split(/[:;\s]+/)[0]
end
end
end
......@@ -23,23 +23,5 @@ module Paperclip
FileUtils.cp(src.path, destination.path)
destination
end
def best_content_type_option(types)
best = types.reject {|type| type.content_type.match(/\/x-/) }
if best.size == 0
types.first.content_type
else
best.first.content_type
end
end
def type_from_file_command
# On BSDs, `file` doesn't give a result code of 1 if the file doesn't exist.
type = (File.extname(self.path.to_s)).downcase
type = "octet-stream" if type.empty?
mime_type = Paperclip.run("file", "-b --mime :file", :file => self.path).split(/[:;\s]+/)[0]
mime_type = "application/x-#{type}" if mime_type.match(/\(.*?\)/)
mime_type
end
end
end
......@@ -11,20 +11,9 @@ module Paperclip
@original_filename = @target.original_filename if @target.respond_to?(:original_filename)
@original_filename ||= File.basename(@target.path)
@tempfile = copy_to_tempfile(@target)
@content_type = calculate_content_type
@content_type = ContentTypeDetector.new(@target.path).detect
@size = File.size(@target)
end
def calculate_content_type
types = MIME::Types.type_for(original_filename)
if types.length == 0
type_from_file_command
elsif types.length == 1
types.first.content_type
else
best_content_type_option(types)
end
end
end
end
......
require './test/helper'
class ContentTypeDetectorTest < Test::Unit::TestCase
context 'given a name' do
should 'return a content type based on that name' do
@filename = "/path/to/something.jpg"
assert_equal "image/jpeg", Paperclip::ContentTypeDetector.new(@filename).detect
end
should 'return a content type based on the content of the file' do
tempfile = Tempfile.new("something")
tempfile.write("This is a file.")
tempfile.rewind
assert_equal "text/plain", Paperclip::ContentTypeDetector.new(tempfile.path).detect
end
should 'return a sensible default if something goes wrong' do
@filename = "/path/to/something"
assert_equal "application/octet-stream", Paperclip::ContentTypeDetector.new(@filename).detect
end
should 'let errors raise if something blows up' do
Paperclip.stubs(:run).raises(Cocaine::CommandLineError.new)
@filename = "/path/to/something"
assert_raises(Cocaine::CommandLineError) do
Paperclip::ContentTypeDetector.new(@filename).detect
end
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment