create thumbnails when needed
This commit is contained in:
parent
d4c3fe4e6a
commit
cc9e0ec80a
|
@ -1,7 +1,35 @@
|
||||||
class OptimizedImage < ActiveRecord::Base
|
class OptimizedImage < ActiveRecord::Base
|
||||||
belongs_to :upload
|
belongs_to :upload
|
||||||
|
|
||||||
|
def self.create_for(upload_id, path)
|
||||||
|
image_info = FastImage.new(path)
|
||||||
|
OptimizedImage.new({
|
||||||
|
upload_id: upload_id,
|
||||||
|
sha: Digest::SHA1.file(path).hexdigest,
|
||||||
|
ext: File.extname(path),
|
||||||
|
width: image_info.size[0],
|
||||||
|
height: image_info.size[1]
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
"#{Upload.base_url}/#{optimized_path}/#{filename}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def path
|
||||||
|
"#{path_root}/#{optimized_path}/#{filename}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def path_root
|
||||||
|
@path_root ||= "#{Rails.root}/public"
|
||||||
|
end
|
||||||
|
|
||||||
|
def optimized_path
|
||||||
|
"uploads/#{RailsMultisite::ConnectionManagement.current_db}/_optimized/#{sha[0..2]}/#{sha[3..5]}"
|
||||||
|
end
|
||||||
|
|
||||||
def filename
|
def filename
|
||||||
"#{sha[0..2]}/#{sha[3..5]}/#{sha[6..16]}_#{width}x#{height}#{ext}"
|
"#{sha[6..16]}_#{width}x#{height}#{ext}"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,8 @@ require 'digest/sha1'
|
||||||
require 'image_sizer'
|
require 'image_sizer'
|
||||||
require 's3'
|
require 's3'
|
||||||
require 'local_store'
|
require 'local_store'
|
||||||
|
require 'tempfile'
|
||||||
|
require 'pathname'
|
||||||
|
|
||||||
class Upload < ActiveRecord::Base
|
class Upload < ActiveRecord::Base
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
@ -14,6 +16,40 @@ class Upload < ActiveRecord::Base
|
||||||
validates_presence_of :filesize
|
validates_presence_of :filesize
|
||||||
validates_presence_of :original_filename
|
validates_presence_of :original_filename
|
||||||
|
|
||||||
|
def thumbnail
|
||||||
|
@thumbnail ||= optimized_images.where(width: width, height: height).first
|
||||||
|
end
|
||||||
|
|
||||||
|
def thumbnail_url
|
||||||
|
thumbnail.url if has_thumbnail?
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_thumbnail?
|
||||||
|
thumbnail.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_thumbnail!
|
||||||
|
return unless SiteSetting.create_thumbnails?
|
||||||
|
return unless width > SiteSetting.auto_link_images_wider_than
|
||||||
|
return if has_thumbnail?
|
||||||
|
@image_sorcery_loaded ||= require "image_sorcery"
|
||||||
|
original_path = "#{Rails.root}/public#{url}"
|
||||||
|
temp_file = Tempfile.new(["discourse", File.extname(original_path)])
|
||||||
|
if ImageSorcery.new(original_path).convert(temp_file.path, resize: "#{width}x#{height}")
|
||||||
|
thumbnail = OptimizedImage.create_for(id, temp_file.path)
|
||||||
|
optimized_images << thumbnail
|
||||||
|
# make sure the directory exists
|
||||||
|
FileUtils.mkdir_p Pathname.new(thumbnail.path).dirname
|
||||||
|
# move the temp file to the right location
|
||||||
|
File.open(thumbnail.path, "wb") do |f|
|
||||||
|
f.write temp_file.read
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# close && remove temp file if it exists
|
||||||
|
temp_file.close
|
||||||
|
temp_file.unlink
|
||||||
|
end
|
||||||
|
|
||||||
def self.create_for(user_id, file)
|
def self.create_for(user_id, file)
|
||||||
# compute the sha
|
# compute the sha
|
||||||
sha = Digest::SHA1.file(file.tempfile).hexdigest
|
sha = Digest::SHA1.file(file.tempfile).hexdigest
|
||||||
|
|
|
@ -9,6 +9,7 @@ class CreateOptimizedImages < ActiveRecord::Migration
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index :optimized_images, :upload_id
|
add_index :optimized_images, :upload_id
|
||||||
|
add_index :optimized_images, [:upload_id, :width, :height], unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
def down
|
def down
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
# example, inserting the onebox content, or image sizes.
|
# example, inserting the onebox content, or image sizes.
|
||||||
|
|
||||||
require_dependency 'oneboxer'
|
require_dependency 'oneboxer'
|
||||||
require_dependency 'image_optimizer'
|
|
||||||
|
|
||||||
class CookedPostProcessor
|
class CookedPostProcessor
|
||||||
|
|
||||||
|
@ -34,10 +33,18 @@ class CookedPostProcessor
|
||||||
if src.present?
|
if src.present?
|
||||||
# make sure the img has both width and height attributes
|
# make sure the img has both width and height attributes
|
||||||
update_dimensions!(img)
|
update_dimensions!(img)
|
||||||
|
# retrieve the associated upload, if any
|
||||||
|
upload = get_upload_from_url(img['src'])
|
||||||
|
if upload.present?
|
||||||
|
# create a thumbnail
|
||||||
|
upload.create_thumbnail!
|
||||||
# optimize image
|
# optimize image
|
||||||
img['src'] = optimize_image(img)
|
img['src'] = optimize_image(img)
|
||||||
# lightbox treatment
|
# lightbox treatment
|
||||||
|
convert_to_link!(img, upload.thumbnail_url)
|
||||||
|
else
|
||||||
convert_to_link!(img)
|
convert_to_link!(img)
|
||||||
|
end
|
||||||
# mark the post as dirty whenever the src has changed
|
# mark the post as dirty whenever the src has changed
|
||||||
@dirty |= src != img['src']
|
@dirty |= src != img['src']
|
||||||
end
|
end
|
||||||
|
@ -74,14 +81,19 @@ class CookedPostProcessor
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def get_upload_from_url(url)
|
||||||
|
if Upload.has_been_uploaded?(url) && m = Upload.uploaded_regex.match(url)
|
||||||
|
Upload.where("id = ?", m[:upload_id]).first
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def optimize_image(img)
|
def optimize_image(img)
|
||||||
return img["src"]
|
return img["src"]
|
||||||
# 1) optimize using image_optim
|
# 1) optimize using image_optim
|
||||||
# 2) .png vs. .jpg
|
# 2) .png vs. .jpg
|
||||||
# TODO: needs some <3
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def convert_to_link!(img)
|
def convert_to_link!(img, thumbnail=nil)
|
||||||
src = img["src"]
|
src = img["src"]
|
||||||
width, height = img["width"].to_i, img["height"].to_i
|
width, height = img["width"].to_i, img["height"].to_i
|
||||||
|
|
||||||
|
@ -99,6 +111,7 @@ class CookedPostProcessor
|
||||||
end
|
end
|
||||||
|
|
||||||
# not a hyperlink so we can apply
|
# not a hyperlink so we can apply
|
||||||
|
img['src'] = thumbnail if thumbnail
|
||||||
a = Nokogiri::XML::Node.new "a", @doc
|
a = Nokogiri::XML::Node.new "a", @doc
|
||||||
img.add_next_sibling(a)
|
img.add_next_sibling(a)
|
||||||
a["href"] = src
|
a["href"] = src
|
||||||
|
|
Loading…
Reference in New Issue