balloon 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,98 @@
1
+ require 'mini_magick'
2
+
3
+ module Balloon
4
+ module Processing
5
+ extend ActiveSupport::Concern
6
+
7
+ def resize_with_string(file)
8
+ width, height = "", ""
9
+ oranginl_img = MiniMagick::Image.open(file.path)
10
+ auto_orient!(oranginl_img, file.path)
11
+ if self.respond_to?(:uploader_size) && !(store_storage.to_s == "upyun" && upyun_is_image)
12
+ uploader_size.each do |s, o|
13
+ img = MiniMagick::Image.open(file.path)
14
+ raise ProcessError, "process error" unless img
15
+ width = img[:width]
16
+ height = img[:height]
17
+ new_img = resize(img, o)
18
+ new_img.write File.join(cache_path, "#{file.basename}_#{s}.#{file.extension}")
19
+ end
20
+ end
21
+ return {width: oranginl_img[:width], height: oranginl_img[:height]}
22
+ end
23
+
24
+ def resize(image, size)
25
+ width, height, symbol = size[:width], size[:height], size[:symbol]
26
+ if !symbol.empty? || width.match(/\%/) || height.match(/\%/)
27
+ if width == height
28
+ image = shave(image)
29
+ image.resize "#{width}"
30
+ else
31
+ image.resize "#{width}x#{height}#{symbol}"
32
+ end
33
+ else
34
+ if width == height
35
+ image = shave(image)
36
+ value = (width.to_f / image[:width].to_f) * 100
37
+ image.resize "#{value}%"
38
+ else
39
+ if width.empty?
40
+ value = (height.to_f / image[:height].to_f) * 100
41
+ image.resize "#{value}%"
42
+ elsif height.empty?
43
+ value = (width.to_f / image[:width].to_f) * 100
44
+ image.resize "#{value}%"
45
+ else
46
+ image.resize "#{width}x#{height}"
47
+ end
48
+ end
49
+ end
50
+ return image
51
+ end
52
+
53
+ def shave(image)
54
+ w, h = image[:width], image[:height]
55
+ if w > h
56
+ shave_off = ((w - h) / 2).round
57
+ image.shave "#{shave_off}x0"
58
+ else
59
+ shave_off = ((h - w) / 2).round
60
+ image.shave "0x#{shave_off}"
61
+ end
62
+ return image
63
+ end
64
+
65
+ def auto_orient!(img, file)
66
+ if img["exif:orientation"] == "6"
67
+ img.auto_orient
68
+ img.write file
69
+ end
70
+ end
71
+
72
+ # parseing the size string
73
+ #
74
+ # @return [Hash] the options for string
75
+ module ClassMethods
76
+ def parsing_size_string(size)
77
+ symbol = ""
78
+ symbol_regex = /[^\d|\!|\>|\<|\%|x|X]/
79
+ if size.include?('x')
80
+ if has_symbol = size.match(/[\!|\>|\<]/)
81
+ symbol = has_symbol[0]
82
+ size_option = size[0, 7].split("x")
83
+ else
84
+ size_option = size.split("x")
85
+ end
86
+ width, height = size_option
87
+ else
88
+ width, height = size, size
89
+ end
90
+ width = width || ""
91
+ width = width.match(symbol_regex) ? "" : width
92
+ height = height || ""
93
+ height = height.match(symbol_regex) ? "" : height
94
+ return { width: width, height: height, symbol: symbol }
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,62 @@
1
+ module Balloon
2
+ module Storage
3
+ class File < Balloon::Storage::Store
4
+ def store!
5
+ _store_path = store_path
6
+
7
+ if !::File.exists? _store_path
8
+ FileUtils.mkdir_p _store_path
9
+ FileUtils.chmod_R @uploader.dir_permissions.to_i, _store_path
10
+ end
11
+
12
+ original_file = set_upload_name
13
+ store_original_file = ::File.join _store_path, original_file
14
+ cache_original_file = ::File.join @uploader.cache_path, @uploader.info[:filename]
15
+ FileUtils.mv cache_original_file, store_original_file
16
+
17
+ if @uploader.respond_to?(:uploader_size)
18
+ @uploader.uploader_size.each do |s, o|
19
+ store_file = ::File.join _store_path, set_upload_name(s)
20
+ cache_file = ::File.join @uploader.cache_path, @uploader.info[:basename]+ "_#{s}"+"."+ @uploader.info[:extension]
21
+ FileUtils.mv cache_file, store_file
22
+ end
23
+ end
24
+ return { filename: original_file, basename: store_name}
25
+ end
26
+
27
+ def retrieve!(size_name = nil)
28
+ return "" if !upload_file
29
+ path = ::File.join upload_dir, store_filename(size_name)
30
+ return "/" + path if @uploader.asset_host.nil?
31
+ @uploader.asset_host + "/" + path
32
+ end
33
+
34
+ def delete!
35
+ return false if !upload_file
36
+ path = ::File.join store_path, store_filename
37
+ FileUtils.rm(path) if ::File.exists?(path)
38
+ if @uploader.respond_to?(:uploader_size)
39
+ @uploader.uploader_size.each do |s, o|
40
+ path = ::File.join store_path, store_filename(s)
41
+ FileUtils.rm(path) if ::File.exists?(path)
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def store_filename(size_name = nil)
49
+ extension = upload_file[:extension].blank? ? "" : "." + upload_file[:extension]
50
+ if size_name.nil?
51
+ upload_file[:basename] + extension
52
+ else
53
+ upload_file[:basename] + "_" + size_name.to_s + extension
54
+ end
55
+ end
56
+
57
+ def store_path
58
+ ::File.expand_path ::File.join(@uploader.root, @uploader.store_dir, upload_dir)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,84 @@
1
+ module Balloon
2
+ module Storage
3
+ class Store
4
+ def initialize(uploader)
5
+ @uploader = uploader
6
+ end
7
+
8
+ def store!; end
9
+
10
+ def retrieve!(size_name = nil); end
11
+
12
+ def upload_file
13
+ file_info = @uploader.info
14
+ return {} if file_info.nil?
15
+ basename = file_info[:basename] || ""
16
+ extension = file_info[:extension] || ""
17
+ { basename: basename, extension: extension }
18
+ end
19
+
20
+ def upload_dir
21
+ @uploader.respond_to?(:uploader_dir) ? @uploader.uploader_dir : @uploader.uploader_name
22
+ end
23
+
24
+ def store_name
25
+ return upload_file[:basename] if !@uploader.respond_to?(:uploader_name_format)
26
+ name_format = @uploader.uploader_name_format
27
+ name = name_format[:name]
28
+ if name_format[:format].to_s == "downcase"
29
+ name = name.downcase
30
+ elsif name_format[:format].to_s == "upcase"
31
+ name = name.upcase
32
+ else
33
+ name
34
+ end
35
+ end
36
+
37
+ def set_upload_name(size_name = nil )
38
+ if size_name
39
+ store_name + "_#{size_name.to_s}" + "." + upload_file[:extension]
40
+ else
41
+ store_name + "." + upload_file[:extension]
42
+ end
43
+ end
44
+
45
+ def connection
46
+ options = self.class.get_option(self)
47
+ basic = self.class.get_basic_auth(self)
48
+ token = self.class.token_auth
49
+ conn = Http::Client.new(options[:url]) do |builder|
50
+ builder.headers = options[:headers]
51
+ builder.basic_auth(basic[:user], basic[:password]) if !basic.nil?
52
+ builder.token_auth(self, token) if !token.nil?
53
+ end
54
+ return conn
55
+ end
56
+
57
+ class << self
58
+ def conn_option(&block)
59
+ return @option_proc unless block_given?
60
+ @option_proc = block
61
+ end
62
+
63
+ def get_option(klass)
64
+ klass.instance_eval(&conn_option)
65
+ end
66
+
67
+ def basic_auth(&block)
68
+ return @basic_proc unless block_given?
69
+ @basic_proc = block
70
+ end
71
+
72
+ def get_basic_auth(klass)
73
+ return nil if basic_auth.nil?
74
+ klass.instance_eval(&basic_auth)
75
+ end
76
+
77
+ def token_auth(&block)
78
+ return @token_proc unless block_given?
79
+ @token_proc = block
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,91 @@
1
+ module Balloon
2
+ module Storage
3
+ class Upyun < Balloon::Storage::Store
4
+
5
+ conn_option do
6
+ {
7
+ url: conn_url,
8
+ headers: conn_headers,
9
+ timeout: @uploader.upyun_timeout
10
+ }
11
+ end
12
+
13
+ token_auth do |method, path, size, date|
14
+ "encode_canonical('#{method}', '#{path}', #{size}, '#{date}')"
15
+ end
16
+
17
+ def store!
18
+ _store_path = store_path
19
+ original_file = set_upload_name
20
+ store_original_file = ::File.join _store_path, original_file
21
+ cache_original_file = ::File.join @uploader.cache_path, @uploader.info[:filename]
22
+ file = ::File.new cache_original_file
23
+ response = connection.put(store_original_file, file.read, file.size)
24
+ raise "Connection errors" if response.nil?
25
+
26
+ if !@uploader.upyun_is_image && @uploader.respond_to?(:uploader_size)
27
+ @uploader.uploader_size.each do |s, o|
28
+ store_file = ::File.join _store_path, set_upload_name(s)
29
+ cache_file = ::File.join @uploader.cache_path, @uploader.info[:basename]+ "_#{s}"+"."+ @uploader.info[:extension]
30
+ file = ::File.new cache_file
31
+ connection.put(store_file, file.read, file.size)
32
+ end
33
+ end
34
+
35
+ return { filename: original_file, basename: store_name }
36
+ end
37
+
38
+ def retrieve!(size_name = nil)
39
+ if !@uploader.upyun_is_image || size_name.nil?
40
+ path = ::File.join upload_dir, store_filename(size_name)
41
+ @uploader.upyun_domain + "/" + path
42
+ else
43
+ filename = store_filename + @uploader.upyun_thumb_symbol + size_name.to_s
44
+ path = ::File.join upload_dir, filename
45
+ @uploader.upyun_domain + "/" + path
46
+ end
47
+ end
48
+
49
+ def delete!
50
+ _store_path = store_path
51
+ store_original_file = ::File.join _store_path, store_filename
52
+ response = connection.delete(store_original_file)
53
+ if !@uploader.upyun_is_image && @uploader.respond_to?(:uploader_size)
54
+ @uploader.uploader_size.each do |s, o|
55
+ store_file = ::File.join _store_path, store_filename(s)
56
+ connection.delete(store_file)
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def encode_canonical(method, path, size, date)
64
+ options = []
65
+ options << method
66
+ options << path
67
+ options << date
68
+ options << size
69
+ options << "#{Digest::MD5.hexdigest(@uploader.upyun_password)}"
70
+ "UpYun #{@uploader.upyun_username}:#{Digest::MD5.hexdigest(options.join("&"))}"
71
+ end
72
+
73
+ def store_filename(size_name = nil)
74
+ return upload_file[:basename] + "." + upload_file[:extension] if size_name == nil
75
+ upload_file[:basename] + "_" + size_name.to_s + "." + upload_file[:extension]
76
+ end
77
+
78
+ def conn_url
79
+ @uploader.upyun_api_host || "http://v0.api.upyun.com"
80
+ end
81
+
82
+ def conn_headers
83
+ @uploader.upyun_headers.merge({ 'Mkdir' => 'true', 'Expect' => '', 'Date' => Time.now.httpdate })
84
+ end
85
+
86
+ def store_path
87
+ ::File.join("/", @uploader.upyun_bucket, upload_dir)
88
+ end
89
+ end
90
+ end
91
+ end
data/lib/balloon/up.rb ADDED
@@ -0,0 +1,100 @@
1
+ module Balloon
2
+ module Up
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include Balloon::Uploader
7
+ include Balloon::Validate
8
+ end
9
+
10
+ module ClassMethods
11
+ def uploader(name, db = nil)
12
+
13
+ before_create :uploader_save
14
+
15
+ class_eval <<-RUBY
16
+ def #{name}=(file)
17
+ save_to_cache(file)
18
+ rescue DownloadError => e
19
+ @download_error = e
20
+ rescue ProcessError => e
21
+ @process_error = e
22
+ end
23
+
24
+ def #{name}
25
+ @info
26
+ end
27
+
28
+ def uploader_save
29
+ return if info.nil?
30
+ set_storage_engine
31
+ store_info = storage_engine.store!
32
+ @info[:filename] = store_info[:filename]
33
+ @info[:basename] = store_info[:basename]
34
+ end
35
+
36
+ def uploader_name
37
+ "#{name}".pluralize
38
+ end
39
+ RUBY
40
+
41
+ set_keyword if db
42
+
43
+ validates_download_of name
44
+ end
45
+
46
+ def set_keyword
47
+ if defined?(MongoMapper)
48
+ key :file_name, String
49
+ key :width, Integer
50
+ key :height, Integer
51
+ key :content_type, String
52
+ key :file_size, Integer
53
+ key :storage, String
54
+ key :created_at
55
+ elsif defined?(Mongoid)
56
+ field :file_name, type: String
57
+ field :width, type: Integer
58
+ field :height, type: Integer
59
+ field :content_type, type: String
60
+ field :file_size, type: String
61
+ field :storage, type: String
62
+ field :created_at
63
+ end
64
+
65
+ before_create :save_db
66
+ after_destroy :uploader_delete
67
+
68
+ class_eval <<-RUBY
69
+ def save_db
70
+ return if info.nil?
71
+ self.file_name = info[:filename]
72
+ self.content_type = info[:mime_type]
73
+ self.file_size = info[:size]
74
+ self.storage = store_storage.to_s
75
+ self.width = info[:width]
76
+ self.height = info[:height]
77
+ end
78
+
79
+ def url(size_name = nil)
80
+ return "" if !respond_to?(:file_name) || file_name.nil?
81
+ extension = self.file_name.to_s.match(%r"(?!\\.{1})\\w{2,}$")
82
+ basename = self.file_name.to_s.gsub(%r"\\.{1}\\w{2,}$",'')
83
+ @info = { basename: basename, extension: extension.to_s }
84
+ set_storage_engine
85
+ storage_engine.retrieve!(size_name)
86
+ end
87
+
88
+ def uploader_delete
89
+ return if !respond_to?(:file_name) || file_name.nil?
90
+ extension = self.file_name.to_s.match(%r"(?!\\.{1})\\w{2,}$")
91
+ basename = self.file_name.to_s.gsub(%r"\\.{1}\\w{2,}$",'')
92
+ @info = { basename: basename, extension: extension.to_s }
93
+ set_storage_engine
94
+ storage_engine.delete!
95
+ end
96
+ RUBY
97
+ end
98
+ end #ClassMethods
99
+ end #Up
100
+ end
@@ -0,0 +1,90 @@
1
+ module Balloon
2
+ module Uploader
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ include Balloon::Configuration
7
+ include Balloon::Processing
8
+ include Balloon::Cache
9
+ include Balloon::Download
10
+ attr_accessor :file
11
+ attr_reader :storage_engine
12
+ attr_reader :info
13
+ attr_accessor :download_error, :process_error
14
+ end
15
+
16
+ def set_storage_engine
17
+ @storage_engine = eval(Balloon::Base::STORAGE_EGINE[store_storage.to_sym]).new(self) if !respond_to?(:@storage_engine)
18
+ end
19
+
20
+ def save_to_cache(up_file)
21
+ uploader_file = up_file.is_a?(String) && up_file.include?("://") ? down_url(up_file) : up_file
22
+
23
+ uploader_file_ext = Balloon::FileExtension.new(uploader_file)
24
+ file_mime_type = uploader_file_ext.mime_type
25
+
26
+ if self.respond_to?(:uploader_mimetype_white)
27
+ if !uploader_mimetype_white.include?(file_mime_type)
28
+ raise Balloon::DownloadError, I18n.translate(:"errors.messages.down_mime_error")
29
+ end
30
+ elsif self.respond_to?(:uploader_mimetype_black)
31
+ if !uploader_mimetype_black.include?(file_mime_type)
32
+ raise Balloon::DownloadError, I18n.translate(:"errors.messages.down_mime_error")
33
+ end
34
+ end
35
+
36
+ generate_cache_directory
37
+ up_file = uploader_file_ext.save_to cache_path, permissions
38
+ uploader_file = up_file
39
+ img = resize_with_string up_file
40
+ @info = {
41
+ width: img[:width],
42
+ height: img[:height],
43
+ size: up_file.size,
44
+ mime_type: up_file.mime_type,
45
+ filename: up_file.filename,
46
+ basename: up_file.basename,
47
+ extension: up_file.extension
48
+ }
49
+ end
50
+
51
+ def url(size_name = nil); end
52
+
53
+ module ClassMethods
54
+ def uploader_dir(name)
55
+ define_method "uploader_dir" do; name; end
56
+ end
57
+
58
+ def uploader_size(options)
59
+ list = {}
60
+
61
+ if options.is_a?(Hash)
62
+ options.each do |key, value|
63
+ list[key] = parsing_size_string(value)
64
+ end
65
+ else
66
+ list[:orignal] = parsing_size_string options
67
+ end
68
+
69
+ define_method "uploader_size" do; list; end
70
+ end
71
+
72
+ def uploader_name_format(info)
73
+ define_method "uploader_name_format" do
74
+ name = info[:name].nil? ? info[:name] : info[:name].call(self)
75
+ { name: name, format: info[:format] }
76
+ end
77
+ end
78
+
79
+ def uploader_mimetype_white(list)
80
+ raise "just choise one method" if respond_to?(:uploader_mime_type_black)
81
+ define_method "uploader_mimetype_white" do; list; end
82
+ end
83
+
84
+ def uploader_mimetype_black(list)
85
+ raise "just choise one method" if respond_to?(:uploader_mime_type_black)
86
+ define_method "uploader_mimetype_black" do; list; end
87
+ end
88
+ end
89
+ end #Uploader
90
+ end