Skip to content
Browse files

Merge pull request #9 from abdulrauf/master

Support for S3 and Asset Library Code refactoring
  • Loading branch information...
2 parents 11e8b73 + f9dd134 commit 2094f5054c805eea8d2b6064c6a2a0b5e6daa221 @yuritomanek yuritomanek committed
View
5 app/controllers/gluttonberg/admin/asset_library/assets_controller.rb
@@ -83,7 +83,10 @@ def show
end
def destroy_assets_in_bulk
- @assets = Asset.delete_all(:id => params[:asset_ids].split(","))
+ @assets = Asset.where(:id => params[:asset_ids].split(",")).all
+ @assets.each do |asset|
+ asset.destroy
+ end
redirect_to "/admin/browse/all/page/1"
end
View
23 app/helpers/gluttonberg/asset_library.rb
@@ -1,20 +1,23 @@
module Gluttonberg
module AssetLibrary
- # nice and clean public url of assets
- def asset_url(asset , opts = {})
- url = ""
- if Rails.env=="development"
+ # nice and clean public url of assets
+ def asset_url(asset , opts = {})
+ url = ""
+ if Rails.configuration.asset_storage == :s3
+ url = asset.url
+ else
+ if Rails.env=="development"
url = "http://#{request.host}:#{request.port}/user_asset/#{asset.asset_hash[0..3]}/#{asset.id}"
- else
+ else
url = "http://#{request.host}/user_asset/#{asset.asset_hash[0..3]}/#{asset.id}"
- end
+ end
- if opts[:thumb_name]
+ if opts[:thumb_name]
url << "/#{opts[:thumb_name]}"
- end
-
- url
+ end
+ end
+ url
end
View
8 app/models/gluttonberg/asset.rb
@@ -4,7 +4,7 @@ class Asset < ActiveRecord::Base
has_many :set_elements, :as => :element
has_many :asset_thumbnails
- after_save :update_file
+ #after_save :update_file
before_validation :set_category_and_type
acts_as_taggable_on :locations , :characters , :themes, :photographers
@@ -167,9 +167,9 @@ def copy_audios_to_s3
private
# make a new asset folder if not exist. then make backup of asset. generate thumbnails
- def update_file
- update_file_on_disk
- end
+ # def update_file
+ # update_file_on_disk
+ # end
end
View
3 app/models/gluttonberg/setting.rb
@@ -58,15 +58,12 @@ def dropdown_required?
!values_list.blank?
end
-
def parsed_values_list_for_dropdown
unless values_list.blank?
values_list.split(";")
end
end
-
-
def self.get_setting(key)
if Gluttonberg::Setting.table_exists?
data = nil
View
3 lib/engine.rb
@@ -23,6 +23,7 @@ class Engine < Rails::Engine
config.honeypot_field_name = "our_newly_weekly_series"
config.custom_css_for_cms = false
config.custom_js_for_cms = false
+ config.asset_storage = :filesystem
#engines which depends on gluttonberg-core can
#use this to provide additional processor for assets
#in first stage I am going to use it with Tv
@@ -87,7 +88,7 @@ class Engine < Rails::Engine
end
initializer "setup gluttonberg asset library" do |app|
- Gluttonberg::Library.setup
+ #Gluttonberg::Library.setup
require "acts-as-taggable-on"
if ::ActsAsTaggableOn::Tag.attribute_names.include?("slug") == true
::ActsAsTaggableOn::Tag.send(:include , Gluttonberg::Content::SlugManagement)
View
2 lib/gluttonberg/content.rb
@@ -1,6 +1,6 @@
content = Pathname(__FILE__).dirname.expand_path
-require File.join(content, 'content', 'slug_management')
+require File.join(content, "content", "slug_management")
require File.join(content, "content", "block")
require File.join(content, "content", "block_localization")
require File.join(content, "content", "localization")
View
173 lib/gluttonberg/library.rb
@@ -1,44 +1,47 @@
library = Pathname(__FILE__).dirname.expand_path
require File.join(library, "library", "attachment_mixin")
require File.join(library, "library", "quick_magick")
+require File.join(library, "library", "storage")
+require File.join(library, "library", "processor")
+require File.join(library, "library", "config")
module Gluttonberg
- # The library module encapsulates the few bits of functionality that lives
- # outside of the library models and controllers. It contains some
+ # The library module encapsulates the few bits of functionality that lives
+ # outside of the library models and controllers. It contains some
# configuration details and is responsible for bootstrapping the various bits
# of meta-data used when categorising uploaded assets.
module Library
UNCATEGORISED_CATEGORY = 'uncategorised'
-
+
@@assets_root = nil
@@test_assets_root = nil
-
+ @@tmp_assets_root = nil
+
def self.bootstrap
build_default_asset_types
end
-
- # Is run when the slice is loaded. It makes sure that all the required
- # directories for storing assets are in the public dir, creating them if
- # they are missing. It also stores the various paths so they can be
- # retreived using the assets_dir method.
- def self.setup
- #logger.info("AssetLibrary is checking for asset folder")
- @@assets_root = "public/user_assets"
- @@test_assets_root = "public/test_assets"
- FileUtils.mkdir(root) unless File.exists?(root) || File.symlink?(root)
+
+ def self.set_asset_root(asset_root , tmp_asset_root , test_asset_root)
+ @@assets_root = asset_root
+ @@tmp_assets_root = tmp_asset_root
+ @@test_assets_root = test_asset_root
end
-
+
# Returns the path to the directory where assets are stored.
def self.root
if ::Rails.env == "test"
@@test_assets_root
- else
+ else
@@assets_root
- end
+ end
+ end
+
+ def self.tmp_root
+ @@tmp_assets_root
end
- # This method is mainly for administrative purposes. It will rebuild the
+ # This method is mainly for administrative purposes. It will rebuild the
# table of asset types, then recategorise each asset.
def self.rebuild
Asset.clear_all_asset_types
@@ -56,79 +59,79 @@ def self.flush_asset_types
# Adds a the inbuilt asset types to the database.
def self.build_default_asset_types
begin
- # ensure that all the categories exist
- AssetCategory.build_defaults
- ensure_type('Unknown Image', 'image', AssetCategory.image_category)
- ensure_type('Unknown Video', 'video', AssetCategory.video_category)
- ensure_type('Unknown Audio', 'audio', AssetCategory.audio_category)
- ensure_type('Unknown File', 'multi-part model message unknown', AssetCategory.uncategorised_category)
-
- ensure_type('Jpeg Image', 'image/jpeg image/pjpeg', AssetCategory.image_category)
- ensure_type('Gif Image', 'image/gif', AssetCategory.image_category)
- ensure_type('Png Image', 'image/png', AssetCategory.image_category)
- ensure_type('Tiff Image', 'image/tiff', AssetCategory.image_category)
- ensure_type('Adobe Photoshop Image', 'image/vnd.adobe.photoshop', AssetCategory.image_category)
- ensure_type('Autocad Image', 'image/vnd.dwg', AssetCategory.image_category)
- ensure_type('Autocad Image', 'image/vnd.dxf', AssetCategory.image_category)
- ensure_type('Icon Image', 'image/vnd.microsoft.icon', AssetCategory.image_category)
- ensure_type('Bitmap Image', 'image/x-bmp image/bmp image/x-win-bmp', AssetCategory.image_category)
- ensure_type('Paintshop Pro Image', 'image/x-paintshoppro', AssetCategory.image_category)
- ensure_type('Mobile Image (plb,psb,pvb)', 'application/vnd.3gpp.pic-bw-large application/vnd.3gpp.pic-bw-small application/vnd.3gpp.pic-bw-var', AssetCategory.image_category)
-
- ensure_type('Moile Audio (3gpp,3gpp2)', 'audio/3gpp audio/3gpp2', AssetCategory.audio_category)
- ensure_type('Dolby Digital Audio (ac3)', 'audio/ac3', AssetCategory.audio_category)
- ensure_type('Mpeg Audio (mpga,mp2,mp3,mp4,mpa)', 'audio/mpeg audio/mpeg4-generic audio/mp4 audio/mpa-robust', AssetCategory.audio_category) # @mpga,mp2,mp3
- ensure_type('Aiff Audio (aif,aifc,aiff)', 'audio/x-aiff', AssetCategory.audio_category)
- ensure_type('Midi Audio (mid,midi,kar)', 'audio/x-midi', AssetCategory.audio_category)
- ensure_type('Real Audio (rm,ram,ra)', 'audio/x-pn-realaudio audio/x-realaudio', AssetCategory.audio_category)
- ensure_type('Wav Audio (wav)', 'audio/x-wav', AssetCategory.audio_category)
- ensure_type('Ogg Vorbis Audio (ogg)', 'application/ogg', AssetCategory.audio_category)
-
- ensure_type('Mobile Video', 'video/3gpp video/3gpp-tt video/3gpp2', AssetCategory.video_category) # @3gp,3gpp 'RFC3839,DRAFT:draft-gellens-mime-bucket
- ensure_type('Digital Video', 'video/DV', AssetCategory.video_category) # RFC3189
- ensure_type('Compressed Video', 'application/mpeg4-iod-xmt application/mpeg4-iod application/mpeg4-generic video/mp4 application/mp4 video/MPV video/mpeg4-generic video/mpeg video/MP2T video/H261 video/H263 video/H263-1998 video/H263-2000 video/H264 video/MP1S video/MP2P', AssetCategory.video_category) # RFC3555
- ensure_type('Jpeg Video', 'video/JPEG video/MJ2', AssetCategory.video_category) # RFC3555
- ensure_type('Quicktime Video', 'video/quicktime', AssetCategory.video_category)
- ensure_type('Uncompressed Video', 'video/raw', AssetCategory.video_category)
- ensure_type('Mpeg Playlist (mxu,m4u)', 'video/vnd.mpegurl', AssetCategory.video_category)
- ensure_type('Avi Video (avi)', 'video/x-msvideo', AssetCategory.video_category)
- ensure_type('Flash Video', 'video/x-flv', AssetCategory.video_category)
-
- ensure_type('M4v Video', 'video/x-m4v', AssetCategory.video_category)
-
- #document category
- ensure_type('Generic Document', 'application/x-csh application/x-dvi application/oda application/pgp-encrypted application/pgp-keys application/pgp-signature', AssetCategory.document_category)
- ensure_type('Calendar Document', 'text/calendar text/x-vcalendar', AssetCategory.document_category)
- ensure_type('Comma Seperated Values Document (csv)', 'text/csv text/comma-separated-values', AssetCategory.document_category)
- ensure_type('Tab Seperated Values Text Document', 'text/tab-separated-values', AssetCategory.document_category)
- ensure_type('Web Document', 'text/html', AssetCategory.document_category)
- ensure_type('Plain Text Document', 'text/plain', AssetCategory.document_category)
- ensure_type('Rich Text Document', 'text/richtext text/rtf', AssetCategory.document_category)
- ensure_type('Sgml Document', 'text/sgml', AssetCategory.document_category)
- ensure_type('Wap Document', 'text/vnd.wap.wml text/vnd.wap.wmlscript', AssetCategory.document_category)
- ensure_type('XML Document', 'text/xml text/xml-external-parsed-entity', AssetCategory.document_category)
- ensure_type('V-Card Document (vcf)', 'text/x-vcard', AssetCategory.document_category)
- ensure_type('Apple Macintosh Document (hqx)', 'application/mac-binhex40', AssetCategory.document_category)
- ensure_type('Adobe Acrobat Document (pdf)', 'application/pdf', AssetCategory.document_category)
- ensure_type('Microsoft Word Document (doc,dot,docx)', 'application/msword application/word', AssetCategory.document_category)
- ensure_type('Microsoft Powerpoint Document (ppt,pps,pot,pptx)', 'application/vnd.ms-powerpoint application/powerpoint', AssetCategory.document_category)
- ensure_type('Microsoft Excel Document (xls,xlt,xlsx)', 'application/vnd.ms-excel application/excel', AssetCategory.document_category)
- ensure_type('Microsoft Works Document', 'application/vnd.ms-works', AssetCategory.document_category)
- ensure_type('Microsoft Project Document (mpp)', 'application/vnd.ms-project', AssetCategory.document_category)
- ensure_type('Microsoft Visio Document (vsd,vst,vsw,vss)', 'application/vnd.visio', AssetCategory.document_category)
- ensure_type('HTML Help Document (chm)', 'application/x-chm', AssetCategory.document_category)
-
-
+ # ensure that all the categories exist
+ AssetCategory.build_defaults
+ ensure_type('Unknown Image', 'image', AssetCategory.image_category)
+ ensure_type('Unknown Video', 'video', AssetCategory.video_category)
+ ensure_type('Unknown Audio', 'audio', AssetCategory.audio_category)
+ ensure_type('Unknown File', 'multi-part model message unknown', AssetCategory.uncategorised_category)
+
+ ensure_type('Jpeg Image', 'image/jpeg image/pjpeg', AssetCategory.image_category)
+ ensure_type('Gif Image', 'image/gif', AssetCategory.image_category)
+ ensure_type('Png Image', 'image/png', AssetCategory.image_category)
+ ensure_type('Tiff Image', 'image/tiff', AssetCategory.image_category)
+ ensure_type('Adobe Photoshop Image', 'image/vnd.adobe.photoshop', AssetCategory.image_category)
+ ensure_type('Autocad Image', 'image/vnd.dwg', AssetCategory.image_category)
+ ensure_type('Autocad Image', 'image/vnd.dxf', AssetCategory.image_category)
+ ensure_type('Icon Image', 'image/vnd.microsoft.icon', AssetCategory.image_category)
+ ensure_type('Bitmap Image', 'image/x-bmp image/bmp image/x-win-bmp', AssetCategory.image_category)
+ ensure_type('Paintshop Pro Image', 'image/x-paintshoppro', AssetCategory.image_category)
+ ensure_type('Mobile Image (plb,psb,pvb)', 'application/vnd.3gpp.pic-bw-large application/vnd.3gpp.pic-bw-small application/vnd.3gpp.pic-bw-var', AssetCategory.image_category)
+
+ ensure_type('Moile Audio (3gpp,3gpp2)', 'audio/3gpp audio/3gpp2', AssetCategory.audio_category)
+ ensure_type('Dolby Digital Audio (ac3)', 'audio/ac3', AssetCategory.audio_category)
+ ensure_type('Mpeg Audio (mpga,mp2,mp3,mp4,mpa)', 'audio/mpeg audio/mpeg4-generic audio/mp4 audio/mpa-robust', AssetCategory.audio_category) # @mpga,mp2,mp3
+ ensure_type('Aiff Audio (aif,aifc,aiff)', 'audio/x-aiff', AssetCategory.audio_category)
+ ensure_type('Midi Audio (mid,midi,kar)', 'audio/x-midi', AssetCategory.audio_category)
+ ensure_type('Real Audio (rm,ram,ra)', 'audio/x-pn-realaudio audio/x-realaudio', AssetCategory.audio_category)
+ ensure_type('Wav Audio (wav)', 'audio/x-wav', AssetCategory.audio_category)
+ ensure_type('Ogg Vorbis Audio (ogg)', 'application/ogg', AssetCategory.audio_category)
+
+ ensure_type('Mobile Video', 'video/3gpp video/3gpp-tt video/3gpp2', AssetCategory.video_category) # @3gp,3gpp 'RFC3839,DRAFT:draft-gellens-mime-bucket
+ ensure_type('Digital Video', 'video/DV', AssetCategory.video_category) # RFC3189
+ ensure_type('Compressed Video', 'application/mpeg4-iod-xmt application/mpeg4-iod application/mpeg4-generic video/mp4 application/mp4 video/MPV video/mpeg4-generic video/mpeg video/MP2T video/H261 video/H263 video/H263-1998 video/H263-2000 video/H264 video/MP1S video/MP2P', AssetCategory.video_category) # RFC3555
+ ensure_type('Jpeg Video', 'video/JPEG video/MJ2', AssetCategory.video_category) # RFC3555
+ ensure_type('Quicktime Video', 'video/quicktime', AssetCategory.video_category)
+ ensure_type('Uncompressed Video', 'video/raw', AssetCategory.video_category)
+ ensure_type('Mpeg Playlist (mxu,m4u)', 'video/vnd.mpegurl', AssetCategory.video_category)
+ ensure_type('Avi Video (avi)', 'video/x-msvideo', AssetCategory.video_category)
+ ensure_type('Flash Video', 'video/x-flv', AssetCategory.video_category)
+
+ ensure_type('M4v Video', 'video/x-m4v', AssetCategory.video_category)
+
+ #document category
+ ensure_type('Generic Document', 'application/x-csh application/x-dvi application/oda application/pgp-encrypted application/pgp-keys application/pgp-signature', AssetCategory.document_category)
+ ensure_type('Calendar Document', 'text/calendar text/x-vcalendar', AssetCategory.document_category)
+ ensure_type('Comma Seperated Values Document (csv)', 'text/csv text/comma-separated-values', AssetCategory.document_category)
+ ensure_type('Tab Seperated Values Text Document', 'text/tab-separated-values', AssetCategory.document_category)
+ ensure_type('Web Document', 'text/html', AssetCategory.document_category)
+ ensure_type('Plain Text Document', 'text/plain', AssetCategory.document_category)
+ ensure_type('Rich Text Document', 'text/richtext text/rtf', AssetCategory.document_category)
+ ensure_type('Sgml Document', 'text/sgml', AssetCategory.document_category)
+ ensure_type('Wap Document', 'text/vnd.wap.wml text/vnd.wap.wmlscript', AssetCategory.document_category)
+ ensure_type('XML Document', 'text/xml text/xml-external-parsed-entity', AssetCategory.document_category)
+ ensure_type('V-Card Document (vcf)', 'text/x-vcard', AssetCategory.document_category)
+ ensure_type('Apple Macintosh Document (hqx)', 'application/mac-binhex40', AssetCategory.document_category)
+ ensure_type('Adobe Acrobat Document (pdf)', 'application/pdf', AssetCategory.document_category)
+ ensure_type('Microsoft Word Document (doc,dot,docx)', 'application/msword application/word', AssetCategory.document_category)
+ ensure_type('Microsoft Powerpoint Document (ppt,pps,pot,pptx)', 'application/vnd.ms-powerpoint application/powerpoint', AssetCategory.document_category)
+ ensure_type('Microsoft Excel Document (xls,xlt,xlsx)', 'application/vnd.ms-excel application/excel', AssetCategory.document_category)
+ ensure_type('Microsoft Works Document', 'application/vnd.ms-works', AssetCategory.document_category)
+ ensure_type('Microsoft Project Document (mpp)', 'application/vnd.ms-project', AssetCategory.document_category)
+ ensure_type('Microsoft Visio Document (vsd,vst,vsw,vss)', 'application/vnd.visio', AssetCategory.document_category)
+ ensure_type('HTML Help Document (chm)', 'application/x-chm', AssetCategory.document_category)
+
+
rescue => e
puts "asset library init fails."
puts e
- end
+ end
end
private
-
- # Makes sure the specified type exists in the DB, if it doesn’t it creates
+
+ # Makes sure the specified type exists in the DB, if it doesn’t it creates
# a new record.
def self.ensure_type(name, mime_type, category)
asset_type = AssetType.first( :conditions => "name = '#{name}'" )
@@ -145,7 +148,5 @@ def self.ensure_type(name, mime_type, category)
asset_type.save
end
-
-
end # Library
end # Gluttonberg
View
319 lib/gluttonberg/library/attachment_mixin.rb
@@ -6,35 +6,38 @@ module Library
# Asset class for each major category of assets e.g. ImageAsset,
# DocumentAsset.
- require "mp3info"
-
module AttachmentMixin
- # Default sizes used when thumbnailing an image.
- DEFAULT_THUMBNAILS = {
- :small_thumb => {:label => "Small Thumb", :filename => "_thumb_small", :geometry => "360x268#" },
- :large_thumb => {:label => "Large Thumb", :filename => "_thumb_large", :geometry => "360x268>"},
- :backend_logo => {:label => "Backend Logo", :filename => "_backend_logo", :geometry => "1000x30"}
- }
-
- # The default max image size. This can be overwritten on a per project
- # basis via the rails configuration.
- MAX_IMAGE_SIZE = "2000x2000>" #Resize image to have specified area in pixels. Aspect ratio is preserved.
-
def self.included(klass)
klass.class_eval do
-
- after_destroy :remove_file_from_disk
+ after_destroy :remove_file_from_storage
before_save :generate_reference_hash
+ after_save :update_file_on_storage
+ attr_accessor :file_dirty
extend ClassMethods
include InstanceMethods
+ extend Library::Config::ImageSizes::ClassMethods
+ include Library::Config::ImageSizes::InstanceMethods
+ initialize_storage()
end
end
+
module ClassMethods
+ def initialize_storage
+ storage_class_name = Rails.configuration.asset_storage.to_s.downcase.camelize
+ begin
+ storage_module = Gluttonberg::Library::Storage.const_get(storage_class_name)
+ rescue NameError
+ raise Exception, "Cannot load storage module '#{storage_class_name}'"
+ end
+ include(storage_module.const_get("InstanceMethods"))
+ extend(storage_module.const_get("ClassMethods"))
+ end
+
# Generate auto titles for those assets without name
def generate_name
@@ -47,24 +50,6 @@ def generate_name
'done' # this just makes the output nicer when running from slice -i
end
- # Returns a collection of thumbnail definitions — sizes, filename etc. —
- # which is a merge of defaults and any custom thumbnails defined by the
- # user.
- def sizes
- @thumbnail_sizes ||= if Rails.configuration.thumbnails
- Rails.configuration.thumbnails.merge(DEFAULT_THUMBNAILS)
- else
- DEFAULT_THUMBNAILS
- end
- end
-
- # Returns the max image size as a hash containing :width and :height.
- # May be the default, or the value configured for a particular project.
- def max_image_size
- Rails.configuration.max_image_size || MAX_IMAGE_SIZE
- end
-
-
end #ClassMethods
@@ -86,11 +71,11 @@ def file=(new_file)
clean_filename = 'thumb.#{file_extension}'
end
-
self.mime_type = new_file.content_type
self.file_name = clean_filename
self.size = new_file.size
@file = new_file
+ self.file_dirty = true
end
end
@@ -103,34 +88,18 @@ def file_extension
file_name.split(".").last
end
- # Returns the public URL to this asset, relative to the domain.
- def url
- "/user_assets/#{asset_hash}/#{file_name}"
- end
-
def asset_folder_path
- "/user_assets/#{asset_hash}"
- end
-
- # Returns the URL for the specified image size.
-
- def url_for(name)
- if self.class.sizes.has_key? name
- filename = self.class.sizes[name][:filename]
- "/user_assets/#{asset_hash}/#{filename}.#{file_extension}"
- end
+ # "/user_assets/#{asset_hash}"
+ directory
end
- # Returns the public URL to the asset’s small thumbnail — relative
- # to the domain.
- def thumb_small_url
- url_for(:small_thumb) if category.downcase == "image"
+ def asset_directory_public_url
+ "#{assets_directory_public_url}/#{asset_hash}"
end
- # Returns the public URL to the asset’s large thumbnail — relative
- # to the domain.
- def thumb_large_url
- url_for(:large_thumb) if category.downcase == "image"
+ # Returns the public URL to this asset, relative to the domain.
+ def url
+ "#{asset_directory_public_url}/#{file_name}"
end
# Returns the full path to the file’s location on disk.
@@ -138,240 +107,56 @@ def location_on_disk
directory + "/" + file_name
end
- # In the case where an uploaded image has been larger that the
- # specified max-size and consequently resized, this method will provide
- # the path to the original, un-altered file.
+ # asset path in actual assets directory
def original_file_on_disk
directory + "/original_" + file_name
end
- # The generated directory where this file is located. If it is an image
- # it’s thumbnails will be stored here as well.
- def directory
- Library.setup
- Library.root + "/" + self.asset_hash
+ # Returns the full path to the file's location on disk in tmp directory.
+ def tmp_location_on_disk
+ tmp_directory + "/" + file_name
end
- def suggested_measures(object , required_geometry)
- required_geometry = required_geometry.delete("#")
- required_geometry_tokens = required_geometry.split("x")
- actual_width = object.width.to_i
- actual_height = object.height.to_i
- required_width = required_geometry_tokens.first.to_i
- required_height = required_geometry_tokens.last.to_i
-
- ratio_required = required_width.to_f / required_height
- ratio_actual = actual_width.to_f / actual_height
-
- crossover_ratio = required_height.to_f / actual_height
- crossover_ratio2 = required_width.to_f / actual_width
-
- if(crossover_ratio < crossover_ratio2 )
- crossover_ratio = crossover_ratio2
- end
-
- projected_height = actual_height * crossover_ratio
-
- if(projected_height < required_height )
- required_width = required_width * (1 + (ratio_actual - ratio_required ) )
- end
- projected_width = actual_width * crossover_ratio
-
- "#{(projected_width).ceil}x#{(projected_width/ratio_actual).ceil}"
- end
-
- def generate_cropped_image(x , y , w , h, image_type)
-
- asset_thumb = self.asset_thumbnails.find(:first , :conditions => {:thumbnail_type => image_type.to_s })
- if asset_thumb.blank?
- asset_thumb = self.asset_thumbnails.create({:thumbnail_type => image_type.to_s , :user_generated => true })
- else
- asset_thumb.update_attributes(:user_generated => true)
- end
-
- path = original_file_on_disk
- original_ext = original_file_on_disk.split(".").last
- path = File.join(directory, "#{self.class.sizes[image_type.to_sym][:filename]}.#{file_extension}") unless image_type.blank?
- begin
- image = QuickMagick::Image.read(original_file_on_disk).first
- rescue
- image = QuickMagick::Image.read(original_file_on_disk).first
- end
- begin
- thumb_defined_width = self.class.sizes[image_type.to_sym][:geometry].split('x').first#.to_i
- scaling_percent = (thumb_defined_width.to_i/(w.to_i*1.0))*100
- image.arguments << " -crop #{w}x#{h}+#{x}+#{y} +repage"
- if scaling_percent != 1.0
- image.arguments << " -resize #{scaling_percent}%"
- end
- rescue => e
- puts e
- end
- image.save path
+ # asset full path in tmp directory
+ def tmp_original_file_on_disk
+ tmp_directory + "/original_" + file_name
end
- # Create thumbnailed versions of image attachements.
- # TODO: generate thumbnails with the correct extension
- def generate_image_thumb
-
- begin
- self.class.sizes.each_pair do |name, config|
-
- asset_thumb = self.asset_thumbnails.find(:first , :conditions => {:thumbnail_type => name.to_s, :user_generated => true })
-
- if asset_thumb.blank?
- #image = QuickMagick::Image.read(location_on_disk).first
- begin
- image = QuickMagick::Image.read(original_file_on_disk).first
- rescue
- image = QuickMagick::Image.read(location_on_disk).first
- end
-
- original_ext = original_file_on_disk.split(".").last
-
- path = File.join(directory, "#{config[:filename]}.#{file_extension}")
- if config[:geometry].include?("#")
- #todo
- begin
- image.resize suggested_measures(image, config[:geometry])
- image.arguments << " -gravity Center -crop #{config[:geometry].delete("#")}+0+0 +repage"
- rescue => e
- puts e
- end
- else
- image.resize config[:geometry]
- end
- image.save path
- end
- end
-
- update_attribute( :custom_thumbnail , true)
- rescue => e
- update_attribute( :custom_thumbnail , false)
+ def generate_cropped_image(x , y , w , h, image_type)
+ if !File.exist?(self.tmp_location_on_disk) && !File.exist?(self.tmp_original_file_on_disk)
+ self.download_asset_to_tmp_file
end
-
+ processor = Library::Processor::Image.new
+ processor.asset = self
+ processor.generate_cropped_image(x , y , w , h, image_type)
+ self.remove_file_from_tmp_storage
end
- def generate_proper_resolution
-
- begin
- make_backup
- begin
- image = QuickMagick::Image.read(original_file_on_disk).first
- rescue => e
- image = QuickMagick::Image.read(location_on_disk).first
- end
-
- actual_width = image.width.to_i
- actual_height = image.height.to_i
-
- update_attributes( :width => actual_width ,:height => actual_height)
-
- image.resize self.class.max_image_size
- image.save File.join(directory, file_name)
- # remove mp3 info if any image have. it may happen in the case of updating asset from mp3 to image
- audio = AudioAssetAttribute.find( :first , :conditions => {:asset_id => asset.id})
- audio.destroy
- rescue #TypeError => error
- # ignore TypeErrors, just means it wasn't a supported image
- update_attribute( :custom_thumbnail , false)
- end
- end
-
-
- # Generates thumbnails for images, but also additionally checks to see
- #TODO if the uploaded image exceeds the specified maximum, in which case it will resize it down.
- def generate_thumb_and_proper_resolution(asset)
- asset.generate_proper_resolution
- asset.generate_image_thumb
- end
-
-
- #TODO Collect mp3 files info using Mp3Info gem
- def collect_mp3_info(asset)
- audio = AudioAssetAttribute.find( :first , :conditions => {:asset_id => asset.id})
-
- begin
- #open mp3 file
- Mp3Info.open(location_on_disk) do |mp3|
- if audio.blank?
- #, :genre => mp3.genre
- AudioAssetAttribute.create( :asset_id => asset.id , :length => mp3.length , :title => mp3.tag.title , :artist => mp3.tag.artist , :album => mp3.tag.album , :tracknum => mp3.tag.tracknum)
- else
- audio.update_attributes( {:length => mp3.length, :genre =>"" , :title => mp3.tag.title , :artist => mp3.tag.artist , :album => mp3.tag.album , :tracknum => mp3.tag.tracknum })
- end
-
- end
- if Gluttonberg::Setting.get_setting("audio_assets") == "Enable"
- Delayed::Job.enqueue AudioJob.new(asset.id)
- end
- rescue => detail
- # if exception occurs and asset has some attributes, then remove them.
- unless audio.blank?
- audio.update_attributes( {:length => nil , :title => nil , :artist => nil , :album => nil , :tracknum => nil })
- end
- end
-
- end
def asset_processing
asset_id_to_process = self.id
asset = Asset.find(:first , :conditions => { :id => asset_id_to_process } )
if asset
- #if it is an image, then create a thumbnail
- if asset.asset_type.asset_category.name == "image"
-
- generate_thumb_and_proper_resolution(asset)
- elsif asset.asset_type.asset_category.name == "audio"
- # If its mp3 file, collect its sound info
- collect_mp3_info(asset)
- end
- #additional processing
- asset_processors = Rails.configuration.asset_processors
- unless asset_processors.blank?
- asset_processors.each do |processor|
- processor.process(asset)
- end
+ asset_processors = [Library::Processor::Image , Library::Processor::Audio] #Core processors
+ asset_processors << Rails.configuration.asset_processors unless Rails.configuration.asset_processors.blank? #additional processors
+ asset_processors = asset_processors.flatten
+ unless asset_processors.blank?
+ asset_processors.each do |processor|
+ processor.process(asset)
end
-
+ end
end
-
- end
+ end # asset_processing
private
- def make_backup
- unless File.exist?(original_file_on_disk)
- FileUtils.cp location_on_disk, original_file_on_disk
- FileUtils.chmod(0755,original_file_on_disk)
- end
- end
-
-
- def remove_file_from_disk
- if File.exists?(directory)
- FileUtils.rm_r(directory)
- end
- end
-
- def update_file_on_disk
- if file
- FileUtils.mkdir(directory) unless File.exists?(directory)
- FileUtils.cp file.tempfile.path, location_on_disk
- FileUtils.chmod(0755, location_on_disk)
-
- # new file has been upload, if its image generate thumbnails, if mp3 collect sound info.
- asset_processing
- end
- end
-
- def generate_reference_hash
- unless self.asset_hash
- self.asset_hash = Digest::SHA1.hexdigest(Time.now.to_s + file_name)
+ def generate_reference_hash
+ unless self.asset_hash
+ self.asset_hash = Digest::SHA1.hexdigest(Time.now.to_s + file_name)
+ end
end
- end
end
end # AttachmentMixin
end #Library
View
10 lib/gluttonberg/library/config.rb
@@ -0,0 +1,10 @@
+library = Pathname(__FILE__).dirname.expand_path
+require File.join(library, "config", "image_sizes")
+
+
+module Gluttonberg
+ module Library
+ module Config
+ end
+ end
+end
View
61 lib/gluttonberg/library/config/image_sizes.rb
@@ -0,0 +1,61 @@
+module Gluttonberg
+ module Library
+ module Config
+ module ImageSizes
+
+ # Default sizes used when thumbnailing an image.
+ DEFAULT_THUMBNAILS = {
+ :small_thumb => {:label => "Small Thumb", :filename => "_thumb_small", :geometry => "360x268#" },
+ :large_thumb => {:label => "Large Thumb", :filename => "_thumb_large", :geometry => "360x268>"},
+ :backend_logo => {:label => "Backend Logo", :filename => "_backend_logo", :geometry => "1000x30"}
+ }
+
+ # The default max image size. This can be overwritten on a per project
+ # basis via the rails configuration.
+ MAX_IMAGE_SIZE = "2000x2000>" #Resize image to have specified area in pixels. Aspect ratio is preserved.
+
+ module ClassMethods
+ # Returns a collection of thumbnail definitions — sizes, filename etc. —
+ # which is a merge of defaults and any custom thumbnails defined by the
+ # user.
+ def sizes
+ @thumbnail_sizes ||= if Rails.configuration.thumbnails
+ Rails.configuration.thumbnails.merge(DEFAULT_THUMBNAILS)
+ else
+ DEFAULT_THUMBNAILS
+ end
+ end
+
+ # Returns the max image size as a hash containing :width and :height.
+ # May be the default, or the value configured for a particular project.
+ def max_image_size
+ Rails.configuration.max_image_size || MAX_IMAGE_SIZE
+ end
+
+ end #ClassMethods
+
+ module InstanceMethods
+ # Returns the URL for the specified image size.
+ def url_for(name)
+ if self.class.sizes.has_key? name
+ filename = self.class.sizes[name][:filename]
+ "#{asset_directory_public_url}/#{filename}.#{file_extension}"
+ end
+ end
+
+ # Returns the public URL to the asset’s small thumbnail — relative
+ # to the domain.
+ def thumb_small_url
+ url_for(:small_thumb) if category.downcase == "image"
+ end
+
+ # Returns the public URL to the asset’s large thumbnail — relative
+ # to the domain.
+ def thumb_large_url
+ url_for(:large_thumb) if category.downcase == "image"
+ end
+ end #InstanceMethods
+ end
+ end
+ end
+end
View
11 lib/gluttonberg/library/processor.rb
@@ -0,0 +1,11 @@
+library = Pathname(__FILE__).dirname.expand_path
+require File.join(library, "processor", "image")
+require File.join(library, "processor", "audio")
+
+
+module Gluttonberg
+ module Library
+ module Processor
+ end
+ end
+end
View
42 lib/gluttonberg/library/processor/audio.rb
@@ -0,0 +1,42 @@
+module Gluttonberg
+ module Library
+ module Processor
+ require "mp3info"
+ class Audio
+ attr_accessor :asset
+
+ def self.process(asset_obj)
+ if asset_obj.asset_type.asset_category.name == "audio"
+ collect_mp3_info(asset)
+ end
+ end
+
+ # Collect mp3 files info using Mp3Info gem
+ def collect_mp3_info(asset)
+ audio = AudioAssetAttribute.find( :first , :conditions => {:asset_id => asset.id})
+
+ begin
+ #open mp3 file
+ Mp3Info.open(location_on_disk) do |mp3|
+ if audio.blank?
+ AudioAssetAttribute.create( :asset_id => asset.id , :length => mp3.length , :title => mp3.tag.title , :artist => mp3.tag.artist , :album => mp3.tag.album , :tracknum => mp3.tag.tracknum)
+ else
+ audio.update_attributes( {:length => mp3.length, :genre =>"" , :title => mp3.tag.title , :artist => mp3.tag.artist , :album => mp3.tag.album , :tracknum => mp3.tag.tracknum })
+ end
+ end
+ if Gluttonberg::Setting.get_setting("audio_assets") == "Enable"
+ Delayed::Job.enqueue AudioJob.new(asset.id)
+ end
+ rescue => detail
+ # if exception occurs and asset has some attributes, then remove them.
+ unless audio.blank?
+ audio.update_attributes( {:length => nil , :title => nil , :artist => nil , :album => nil , :tracknum => nil })
+ end
+ end
+
+ end #collect_mp3_info
+
+ end
+ end
+ end
+end
View
134 lib/gluttonberg/library/processor/image.rb
@@ -0,0 +1,134 @@
+module Gluttonberg
+ module Library
+ module Processor
+ class Image
+
+ attr_accessor :asset
+
+ def self.process(asset_obj)
+ if asset_obj.asset_type.asset_category.name == "image"
+ processor = self.new
+ processor.asset = asset_obj
+ processor.generate_thumb_and_proper_resolution
+ end
+ end
+
+ # Generates thumbnails for images, but also additionally checks to see
+ # if the uploaded image exceeds the specified maximum, in which case it will resize it down.
+ def generate_thumb_and_proper_resolution
+ generate_proper_resolution
+ generate_image_thumb
+ end
+
+ def suggested_measures(object , required_geometry)
+ required_geometry = required_geometry.delete("#")
+ required_geometry_tokens = required_geometry.split("x")
+ actual_width = object.width.to_i
+ actual_height = object.height.to_i
+ required_width = required_geometry_tokens.first.to_i
+ required_height = required_geometry_tokens.last.to_i
+
+ ratio_required = required_width.to_f / required_height
+ ratio_actual = actual_width.to_f / actual_height
+
+ crossover_ratio = required_height.to_f / actual_height
+ crossover_ratio2 = required_width.to_f / actual_width
+
+ if(crossover_ratio < crossover_ratio2 )
+ crossover_ratio = crossover_ratio2
+ end
+
+ projected_height = actual_height * crossover_ratio
+
+ if(projected_height < required_height )
+ required_width = required_width * (1 + (ratio_actual - ratio_required ) )
+ end
+ projected_width = actual_width * crossover_ratio
+
+ "#{(projected_width).ceil}x#{(projected_width/ratio_actual).ceil}"
+ end
+
+ def generate_cropped_image(x , y , w , h, image_type)
+ asset_thumb = asset.asset_thumbnails.find(:first , :conditions => {:thumbnail_type => image_type.to_s })
+ if asset_thumb.blank?
+ asset_thumb = asset.asset_thumbnails.create({:thumbnail_type => image_type.to_s , :user_generated => true })
+ else
+ asset_thumb.update_attributes(:user_generated => true)
+ end
+
+ file_name = "#{asset.class.sizes[image_type.to_sym][:filename]}.#{asset.file_extension}"
+ begin
+ image = QuickMagick::Image.read(asset.tmp_original_file_on_disk).first
+ rescue
+ image = QuickMagick::Image.read(asset.tmp_original_file_on_disk).first
+ end
+ thumb_defined_width = asset.class.sizes[image_type.to_sym][:geometry].split('x').first#.to_i
+ scaling_percent = (thumb_defined_width.to_i/(w.to_i*1.0))*100
+ image.arguments << " -crop #{w}x#{h}+#{x}+#{y} +repage"
+ if scaling_percent != 1.0
+ image.arguments << " -resize #{scaling_percent}%"
+ end
+ image.save File.join(asset.tmp_directory, file_name)
+ asset.move_tmp_file_to_actual_directory(file_name , true)
+ end
+
+ # Create thumbnailed versions of image attachements.
+ # TODO: generate thumbnails with the correct extension
+ def generate_image_thumb
+ asset.class.sizes.each_pair do |name, config|
+ asset_thumb = asset.asset_thumbnails.find(:first , :conditions => {:thumbnail_type => name.to_s, :user_generated => true })
+ if asset_thumb.blank?
+ begin
+ image = QuickMagick::Image.read(asset.tmp_original_file_on_disk).first
+ rescue
+ image = QuickMagick::Image.read(asset.tmp_location_on_disk).first
+ end
+
+ file_name = "#{config[:filename]}.#{asset.file_extension}"
+
+ if config[:geometry].include?("#")
+ #todo
+ begin
+ image.resize(suggested_measures(image, config[:geometry]))
+ image.arguments << " -gravity Center -crop #{config[:geometry].delete("#")}+0+0 +repage"
+ rescue => e
+ puts e
+ end
+ else
+ image.resize config[:geometry]
+ end
+ image.save File.join(asset.tmp_directory, file_name)
+ asset.move_tmp_file_to_actual_directory(file_name, true)
+ end # asset_thumb.blank?
+ end # sizes loop
+
+ asset.update_attribute(:custom_thumbnail , true)
+ end
+
+ def generate_proper_resolution
+ asset.make_backup
+ begin
+ image = QuickMagick::Image.read(asset.tmp_original_file_on_disk).first
+ rescue => e
+ image = QuickMagick::Image.read(asset.tmp_location_on_disk).first
+ end
+
+ actual_width = image.width.to_i
+ actual_height = image.height.to_i
+
+ asset.update_attributes( :width => actual_width ,:height => actual_height)
+
+ image.resize asset.class.max_image_size
+ image.save File.join(asset.tmp_directory, asset.file_name)
+ asset.move_tmp_file_to_actual_directory(asset.file_name , true)
+ # remove mp3 info if any image have. it may happen in the case of updating asset from mp3 to image
+ audio = AudioAssetAttribute.find( :first , :conditions => {:asset_id => asset.id})
+ audio.destroy unless audio.blank?
+ end
+
+
+
+ end
+ end
+ end
+end
View
11 lib/gluttonberg/library/storage.rb
@@ -0,0 +1,11 @@
+library = Pathname(__FILE__).dirname.expand_path
+require File.join(library, "storage", "s3")
+require File.join(library, "storage", "filesystem")
+
+
+module Gluttonberg
+ module Library
+ module Storage
+ end
+ end
+end
View
76 lib/gluttonberg/library/storage/filesystem.rb
@@ -0,0 +1,76 @@
+module Gluttonberg
+ module Library
+ module Storage
+ module Filesystem
+
+ module ClassMethods
+ # It run when the engine is loaded. It makes sure that all the required
+ # directories for storing assets are in the public dir, creating them if
+ # they are missing. It also stores the various paths so they can be
+ # retreived using the assets_dir method.
+ def self.storage_setup
+ Library.set_asset_root("public/user_assets", "public/user_assets", "public/test_assets")
+ FileUtils.mkdir(Library.root) unless File.exists?(Library.root) || File.symlink?(Library.root)
+ end
+ end
+
+ module InstanceMethods
+
+ # The generated directory where this file is located. If it is an image
+ # it’s thumbnails will be stored here as well.
+ def directory
+ Filesystem::ClassMethods.storage_setup if Library.root.blank?
+ Library.root + "/" + self.asset_hash
+ end
+
+ def tmp_directory
+ Filesystem::ClassMethods.storage_setup if Library.tmp_root.blank?
+ Library.tmp_root + "/" + self.asset_hash
+ end
+
+ def assets_directory_public_url
+ "/user_assets"
+ end
+
+ def make_backup
+ unless File.exist?(original_file_on_disk)
+ FileUtils.cp location_on_disk, original_file_on_disk
+ FileUtils.chmod(0755,original_file_on_disk)
+ end
+ end
+
+ def remove_file_from_storage
+ if File.exists?(directory)
+ FileUtils.rm_r(directory)
+ end
+ end
+
+ def remove_file_from_tmp_storage
+ # just dummy method. As we don't need to remove because tmp and actual folder is same for filesystem
+ end
+
+ def update_file_on_storage
+ if file
+ FileUtils.mkdir(directory) unless File.exists?(directory)
+ FileUtils.cp file.tempfile.path, location_on_disk
+ FileUtils.chmod(0755, location_on_disk)
+
+ # new file has been upload, if its image generate thumbnails, if mp3 collect sound info.
+ asset_processing
+ end
+ end
+
+ def move_tmp_file_to_actual_directory(file_name , tmp_file_dirty=true)
+ if self.file_dirty == true
+ self.file_dirty = false
+ end
+ end
+
+ # def write_file_to_disc(src_file_path , )
+ # end
+ end #InstanceMethods
+
+ end #Filesystem
+ end #Storage
+ end #Library
+end #Gluttonberg
View
196 lib/gluttonberg/library/storage/s3.rb
@@ -0,0 +1,196 @@
+module Gluttonberg
+ module Library
+ module Storage
+ module S3
+ module ClassMethods
+ # It run when the engine is loaded. It makes sure that all the required
+ # directories for storing assets are in the public dir, creating them if
+ # they are missing. It also stores the various paths so they can be
+ # retreived using the assets_dir method.
+ TEMP_ASSET_DIRECTORY = "tmp/user_assets"
+ def self.storage_setup
+ Library.set_asset_root("user_assets", TEMP_ASSET_DIRECTORY, "public/test_assets")
+ FileUtils.mkdir(Library.root) unless File.exists?(Library.root) || File.symlink?(Library.root)
+ FileUtils.mkdir(Library.tmp_root) unless File.exists?(Library.tmp_root) || File.symlink?(Library.tmp_root)
+ end
+
+ def self.s3_server_url
+ Gluttonberg::Setting.get_setting("s3_server_url")
+ end
+
+ def self.s3_bucket_name
+ Gluttonberg::Setting.get_setting("s3_bucket")
+ end
+
+ def self.s3_server_key_id
+ Gluttonberg::Setting.get_setting("s3_key_id")
+ end
+
+ def self.s3_server_access_key
+ Gluttonberg::Setting.get_setting("s3_access_key")
+ end
+
+ def self.bucket_handle
+ key_id = S3::ClassMethods.s3_server_key_id
+ key_val = S3::ClassMethods.s3_server_access_key
+ s3_server_url = S3::ClassMethods.s3_server_url
+ s3_bucket = S3::ClassMethods.s3_bucket_name
+ if !key_id.blank? && !key_val.blank? && !s3_server_url.blank? && !s3_bucket.blank?
+ s3 = Aws::S3.new(key_id, key_val, {:server => s3_server_url})
+ bucket = s3.bucket(s3_bucket)
+ else
+ nil
+ end
+ end
+
+ #takes file from public/assets folder and upload to s3 if s3 info is given in CMS settings
+ def self.migrate_file_to_s3(asset_hash , file_name)
+ bucket = bucket_handle
+ unless bucket.blank?
+ local_file = "public/user_assets/" + asset_hash + "/" + file_name
+ key_for_s3 = "user_assets/" + asset_hash + "/" + file_name
+ date = Time.now+1.years
+ key = bucket.key(key_for_s3, true)
+ asset = Gluttonberg::Asset.where(:asset_hash => asset_hash).first
+ unless asset.blank?
+ puts " Copying #{local_file} to #{S3::ClassMethods.s3_bucket_name}"
+ unless asset.mime_type.blank?
+ key.put(File.open(local_file), 'public-read', {"Expires" => date.rfc2822, "content-type" => asset.mime_type})
+ else
+ key.put(File.open(local_file), 'public-read', {"Expires" => date.rfc2822})
+ end
+ Gluttonberg::Asset.update_attributes(:copied_to_s3 => true)
+ puts "Copied"
+ end
+ end
+ end
+
+ end
+
+ module InstanceMethods
+
+ def bucket_handle
+ unless @bucket.blank?
+ @bucket
+ else
+ @bucket = S3::ClassMethods.bucket_handle
+ end
+ end
+
+ # The generated directory where this file is located.
+ def directory
+ S3::ClassMethods.storage_setup if Library.root.blank?
+ Library.root + "/" + self.asset_hash
+ end
+
+ # The generated tmp directory where we will locate this file temporarily for processing.
+ def tmp_directory
+ S3::ClassMethods.storage_setup if Library.tmp_root.blank?
+ Library.tmp_root + "/" + self.asset_hash
+ end
+
+ def s3_bucket_root_url
+ "http://#{S3::ClassMethods.s3_server_url}/#{S3::ClassMethods.s3_bucket_name}"
+ end
+
+ def assets_directory_public_url
+ "#{s3_bucket_root_url}/user_assets"
+ end
+
+ def make_backup
+ unless File.exist?(tmp_original_file_on_disk)
+ FileUtils.cp tmp_location_on_disk, tmp_original_file_on_disk
+ FileUtils.chmod(0755,tmp_original_file_on_disk)
+ move_tmp_file_to_actual_directory("original_" + file_name , true)
+ end
+ end
+
+ def remove_file_from_storage
+ remove_file_from_tmp_storage
+ remove_asset_folder_from_s3
+ end
+
+ def remove_file_from_tmp_storage
+ if File.exists?(tmp_directory)
+ puts "Remove assset folder from tmp storage (tmp_directory)"
+ FileUtils.rm_r(tmp_directory)
+ end
+ end
+
+ def update_file_on_storage
+ if file
+ FileUtils.mkdir(tmp_directory) unless File.exists?(tmp_directory)
+ FileUtils.cp file.tempfile.path, tmp_location_on_disk
+ FileUtils.chmod(0755, tmp_location_on_disk)
+
+ move_tmp_file_to_actual_directory(file_name , false)
+ # new file has been upload, if its image generate thumbnails, if mp3 collect sound info.
+ asset_processing
+ # delete local tmp folder
+ remove_file_from_tmp_storage
+ end
+ end
+
+ def move_tmp_file_to_actual_directory(file_name , tmp_file_dirty=true)
+ if self.file_dirty == true || tmp_file_dirty == true
+ copy_file_to_s3(file_name)
+ self.file_dirty = false
+ end
+ end
+
+ #takes file from tmp folder and upload to s3 if s3 info is given in CMS settings
+ def copy_file_to_s3(file_name)
+ bucket = bucket_handle
+ unless bucket.blank?
+ local_file = self.tmp_directory + "/" + file_name
+ folder = self.asset_hash
+ date = Time.now+1.years
+ puts "Copying #{file_name} (#{local_file}) to #{S3::ClassMethods.s3_bucket_name}"
+ key = bucket.key(self.directory + "/" + file_name, true)
+ unless self.mime_type.blank?
+ key.put(File.open(local_file), 'public-read', {"Expires" => date.rfc2822, "content-type" => self.mime_type})
+ else
+ key.put(File.open(local_file), 'public-read', {"Expires" => date.rfc2822})
+ end
+ self.update_column(:copied_to_s3 , true)
+ puts "Copied"
+ end
+ end
+
+
+
+ # TODO
+ def remove_file_from_s3(file_name)
+ end
+
+ def remove_asset_folder_from_s3
+ bucket = bucket_handle
+ unless bucket.blank?
+ bucket.delete_folder(self.directory)
+ end
+ end
+
+ def download_asset_to_tmp_file
+ download_orginal_file_from_s3
+ end
+
+ def download_orginal_file_from_s3
+ FileUtils.mkdir(self.tmp_directory) unless File.exists?(self.tmp_directory)
+ bucket = bucket_handle
+ key = bucket.key(self.location_on_disk)
+ File.open(self.tmp_location_on_disk, "w") do |f|
+ f.write(key.get)
+ end
+ key = bucket.key(self.original_file_on_disk)
+ if key.exists?
+ File.open(self.tmp_original_file_on_disk, "w") do |f|
+ f.write(key.get)
+ end
+ end
+ end
+
+ end #InstanceMethods
+ end #S3
+ end #Storage
+ end #Library
+end #Gluttonberg
View
28 lib/gluttonberg/tasks/asset.rake
@@ -12,9 +12,14 @@ namespace :gluttonberg do
assets = category.assets #Asset.all
assets.each do |asset|
p "thumb-nailing '#{asset.file_name}' "
- asset.generate_image_thumb
- asset.generate_proper_resolution
- asset.save
+ if !File.exist?(asset.tmp_location_on_disk) && !File.exist?(asset.tmp_original_file_on_disk)
+ asset.download_asset_to_tmp_file
+ end
+ # asset.generate_image_thumb
+ # asset.generate_proper_resolution
+ # asset.save
+ Gluttonberg::Library::Processor::Image.process(asset)
+ asset.remove_file_from_tmp_storage
end
end
end
@@ -44,5 +49,22 @@ namespace :gluttonberg do
Gluttonberg::Asset.update_assets_synopsis_from_csv
end
+ desc "Migrate assets from public/user_assets folder to S3"
+ task :migrate_assets_to_s3 => :environment do
+ Dir.entries("public/user_assets").each do |asset_folder|
+ if !asset_folder.include?(".DS_Store") && File.directory?("public/user_assets/" + asset_folder)
+ Dir.entries("public/user_assets/"+asset_folder).each do |asset_file|
+ if !asset_file.include?(".DS_Store") && !File.directory?("public/user_assets/" + asset_folder+"/"+asset_file)
+ begin
+ Gluttonberg::Library::Storage::S3::ClassMethods.migrate_file_to_s3(asset_folder , asset_file)
+ rescue => e
+ puts "Error: #{e.message}"
+ end
+ end
+ end
+ end
+ end
+ end
+
end
end

0 comments on commit 2094f50

Please sign in to comment.
Something went wrong with that request. Please try again.