Add CarrierWave::MagicMimeTypes mixin

This module extracts the file content-type using ruby-filemagic gem
for more accurate results
This commit is contained in:
Aggelos Avgerinos 2015-02-10 22:45:04 +02:00
parent 5a6745130a
commit 753c4ae17c
4 changed files with 121 additions and 0 deletions

View File

@ -1,3 +1,4 @@
require "carrierwave/processing/rmagick"
require "carrierwave/processing/mini_magick"
require "carrierwave/processing/mime_types"
require "carrierwave/processing/magic_mime_types"

View File

@ -0,0 +1,71 @@
# encoding: utf-8
module CarrierWave
##
# This module simplifies the use of ruby-filemagic gem to intelligently
# and correctly guess and set the content-type of a file. If you want
# to use this, you'll need to require this file:
#
# require 'carrierwave/processing/magic_mime_types'
#
# And then include it in your uploader:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::MagicMimeTypes
# end
#
# You can use the provided helper:
#
# class MyUploader < CarrierWave::Uploader::Base
# include CarrierWave::MagicMimeTypes
#
# process :set_content_type
# end
module MagicMimeTypes
extend ActiveSupport::Concern
included do
begin
require "filemagic"
rescue LoadError => e
e.message << " (You may need to install the ruby-filemagic gem)"
raise e
end
end
module ClassMethods
def set_content_type(override=false)
process :set_content_type => override
end
end
##
# Changes the file content_type using the ruby-filemagic gem
#
# === Parameters
#
# [override (Boolean)] wheter or not to override the file's content_type
# if it is already set, false by default
def set_content_type(override=false)
if override || file.content_type.blank?
File.open(file.path) do |fd|
data = fd.read(1024) || ""
new_content_type = filemagic.buffer(data)
if file.respond_to?(:content_type=)
file.content_type = new_content_type
else
file.instance_variable_set(:@content_type, new_content_type)
end
end
end
end
##
# FileMagic object with the MAGIC_MIME_TYPE flag set
#
# @return [FileMagic] a filemagic object
def filemagic
@filemagic ||= FileMagic.new(FileMagic::MAGIC_MIME_TYPE)
end
end
end

BIN
spec/fixtures/ruby.gif vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View File

@ -0,0 +1,49 @@
# encoding: utf-8
require 'spec_helper'
describe CarrierWave::MagicMimeTypes do
before do
@klass = Class.new(CarrierWave::Uploader::Base) do
attr_accessor :content_type
include CarrierWave::MagicMimeTypes
end
@instance = @klass.new
FileUtils.cp(file_path('ruby.gif'), file_path('ruby_copy.gif'))
@instance.stub(:original_filename).and_return file_path('ruby_copy.gif')
@instance.stub(:file).and_return CarrierWave::SanitizedFile.new(file_path('ruby_copy.gif'))
@file = @instance.file
end
after do
FileUtils.rm(file_path('ruby_copy.gif'))
end
describe "#set_content_type" do
it "does not set the content_type if already set" do
@instance.file.content_type = 'image/jpeg'
@instance.file.should_not_receive(:content_type=)
@instance.set_content_type
end
it "sets content_type if content_type is nil" do
pending
@instance.file.content_type = nil
@instance.file.should_receive(:content_type=).with('image/png')
@instance.set_content_type
end
it "sets content_type if content_type is blank" do
@instance.file.content_type = ''
@instance.file.should_receive(:content_type=).with('image/png')
@instance.set_content_type
end
it "sets content_type if override is true" do
@instance.file.content_type = 'image/png'
@instance.file.should_receive(:content_type=).with('image/png')
@instance.set_content_type(true)
end
end
end