small upload code refactor

This commit is contained in:
Régis Hanol 2015-02-03 18:44:18 +01:00
parent 91b3123e14
commit 0e5c9b2590
10 changed files with 89 additions and 105 deletions

View File

@ -36,7 +36,7 @@ class CategoriesController < ApplicationController
guardian.ensure_can_create!(Category) guardian.ensure_can_create!(Category)
file = params[:file] || params[:files].first file = params[:file] || params[:files].first
upload = Upload.create_for(current_user.id, file.tempfile, file.original_filename, File.size(file.tempfile)) upload = Upload.create_for(current_user.id, file.tempfile, file.original_filename, file.tempfile.size)
if upload.errors.blank? if upload.errors.blank?
render json: { url: upload.url, width: upload.width, height: upload.height } render json: { url: upload.url, width: upload.width, height: upload.height }
else else

View File

@ -4,7 +4,7 @@ class UploadsController < ApplicationController
def create def create
file = params[:file] || params[:files].first file = params[:file] || params[:files].first
filesize = File.size(file.tempfile) filesize = file.tempfile.size
upload = Upload.create_for(current_user.id, file.tempfile, file.original_filename, filesize, { content_type: file.content_type }) upload = Upload.create_for(current_user.id, file.tempfile, file.original_filename, filesize, { content_type: file.content_type })
if upload.errors.empty? && current_user.admin? if upload.errors.empty? && current_user.admin?

View File

@ -13,7 +13,7 @@ class UserAvatarsController < ApplicationController
user.create_user_avatar(user_id: user.id) unless user.user_avatar user.create_user_avatar(user_id: user.id) unless user.user_avatar
user.user_avatar.update_gravatar! user.user_avatar.update_gravatar!
render json: {upload_id: user.user_avatar.gravatar_upload_id} render json: { upload_id: user.user_avatar.gravatar_upload_id }
else else
raise Discourse::NotFound raise Discourse::NotFound
end end

View File

@ -130,12 +130,12 @@ class DiscourseSingleSignOn < SingleSignOn
sso_record.external_avatar_url != avatar_url) sso_record.external_avatar_url != avatar_url)
begin begin
tempfile = FileHelper.download(avatar_url, 1.megabyte, "sso-avatar", true) tempfile = FileHelper.download(avatar_url, SiteSetting.max_image_size_kb.kilobytes, "sso-avatar", true)
ext = FastImage.type(tempfile).to_s ext = FastImage.type(tempfile).to_s
tempfile.rewind tempfile.rewind
upload = Upload.create_for(user.id, tempfile, "external-avatar." + ext, File.size(tempfile.path), { origin: avatar_url }) upload = Upload.create_for(user.id, tempfile, "external-avatar." + ext, tempfile.size, { origin: avatar_url })
user.uploaded_avatar_id = upload.id user.uploaded_avatar_id = upload.id
unless user.user_avatar unless user.user_avatar

View File

@ -15,8 +15,10 @@ class OptimizedImage < ActiveRecord::Base
thumbnail = nil thumbnail = nil
end end
# return the previous thumbnail if any
return thumbnail unless thumbnail.nil?
# create the thumbnail otherwise # create the thumbnail otherwise
unless thumbnail
external_copy = Discourse.store.download(upload) if Discourse.store.external? external_copy = Discourse.store.download(upload) if Discourse.store.external?
original_path = if Discourse.store.external? original_path = if Discourse.store.external?
external_copy.try(:path) external_copy.try(:path)
@ -43,7 +45,7 @@ class OptimizedImage < ActiveRecord::Base
thumbnail = OptimizedImage.create!( thumbnail = OptimizedImage.create!(
upload_id: upload.id, upload_id: upload.id,
sha1: Digest::SHA1.file(temp_path).hexdigest, sha1: Digest::SHA1.file(temp_path).hexdigest,
extension: File.extname(temp_path), extension: extension,
width: width, width: width,
height: height, height: height,
url: "", url: "",
@ -66,7 +68,6 @@ class OptimizedImage < ActiveRecord::Base
# make sure we remove the cached copy from external stores # make sure we remove the cached copy from external stores
external_copy.close! if Discourse.store.external? external_copy.close! if Discourse.store.external?
end
thumbnail thumbnail
end end

View File

@ -50,46 +50,32 @@ class Upload < ActiveRecord::Base
# - content_type # - content_type
# - origin # - origin
def self.create_for(user_id, file, filename, filesize, options = {}) def self.create_for(user_id, file, filename, filesize, options = {})
# compute the sha
sha1 = Digest::SHA1.file(file).hexdigest sha1 = Digest::SHA1.file(file).hexdigest
# check if the file has already been uploaded
upload = Upload.find_by(sha1: sha1) # do we already have that upload?
# delete the previously uploaded file if there's been an error upload = find_by(sha1: sha1)
# make sure the previous upload has not failed
if upload && upload.url.blank? if upload && upload.url.blank?
upload.destroy upload.destroy
upload = nil upload = nil
end end
# create the upload
unless upload # return the previous upload if any
# initialize a new upload return upload unless upload.nil?
upload = Upload.new(
user_id: user_id, # create the upload otherwise
original_filename: filename, upload = Upload.new
filesize: filesize, upload.user_id = user_id
sha1: sha1, upload.original_filename = filename
url: "" upload.filesize = filesize
) upload.sha1 = sha1
# trim the origin if any upload.url = ""
upload.origin = options[:origin][0...1000] if options[:origin] upload.origin = options[:origin][0...1000] if options[:origin]
# check the size of the upload
if FileHelper.is_image?(filename)
if SiteSetting.max_image_size_kb > 0 && filesize >= SiteSetting.max_image_size_kb.kilobytes
upload.errors.add(:base, I18n.t("upload.images.too_large", max_size_kb: SiteSetting.max_image_size_kb))
else
# deal with width & height for images # deal with width & height for images
upload = Upload.resize_image(filename, file, upload) upload = resize_image(filename, file, upload) if FileHelper.is_image?(filename)
end
else
if SiteSetting.max_attachment_size_kb > 0 && filesize >= SiteSetting.max_attachment_size_kb.kilobytes
upload.errors.add(:base, I18n.t("upload.attachments.too_large", max_size_kb: SiteSetting.max_attachment_size_kb))
end
end
# make sure there is no error
return upload unless upload.errors.empty?
# create a db record (so we can use the id)
return upload unless upload.save return upload unless upload.save
# store the file and update its url # store the file and update its url
@ -100,7 +86,6 @@ class Upload < ActiveRecord::Base
else else
upload.errors.add(:url, I18n.t("upload.store_failure", { upload_id: upload.id, user_id: user_id })) upload.errors.add(:url, I18n.t("upload.store_failure", { upload_id: upload.id, user_id: user_id }))
end end
end
# return the uploaded file # return the uploaded file
upload upload

View File

@ -15,22 +15,20 @@ class UserAvatar < ActiveRecord::Base
self.last_gravatar_download_attempt = Time.new self.last_gravatar_download_attempt = Time.new
gravatar_url = "http://www.gravatar.com/avatar/#{email_hash}.png?s=500&d=404" gravatar_url = "http://www.gravatar.com/avatar/#{email_hash}.png?s=500&d=404"
tempfile = FileHelper.download(gravatar_url, 1.megabyte, "gravatar") tempfile = FileHelper.download(gravatar_url, SiteSetting.max_image_size_kb.kilobytes, "gravatar")
upload = Upload.create_for(user.id, tempfile, 'gravatar.png', File.size(tempfile.path)) upload = Upload.create_for(user.id, tempfile, 'gravatar.png', tempfile.size, { origin: gravatar_url })
if gravatar_upload_id != upload.id if gravatar_upload_id != upload.id
gravatar_upload.try(:destroy!) gravatar_upload.try(:destroy!)
self.gravatar_upload = upload self.gravatar_upload = upload
save! save!
else
gravatar_upload
end end
rescue OpenURI::HTTPError rescue OpenURI::HTTPError
save! save!
rescue SocketError rescue SocketError
# skip saving, we are not connected to the net # skip saving, we are not connected to the net
Rails.logger.warn "Failed to download gravatar, socket error - user id #{ user.id }" Rails.logger.warn "Failed to download gravatar, socket error - user id #{user.id}"
ensure ensure
tempfile.close! if tempfile && tempfile.respond_to?(:close!) tempfile.close! if tempfile && tempfile.respond_to?(:close!)
end end

View File

@ -14,9 +14,9 @@ class AvatarUploadService
case source case source
when :url when :url
tmp = FileHelper.download(file, SiteSetting.max_image_size_kb.kilobytes, "discourse-avatar") tmp = FileHelper.download(file, SiteSetting.max_image_size_kb.kilobytes, "discourse-avatar")
[tmp, File.basename(URI.parse(file).path), File.size(tmp)] [tmp, File.basename(URI.parse(file).path), tmp.size]
when :image when :image
[file.tempfile, file.original_filename, File.size(file.tempfile)] [file.tempfile, file.original_filename, file.tempfile.size]
end end
end end

View File

@ -224,7 +224,7 @@ module Email
# read attachment # read attachment
File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded } File.open(tmp.path, "w+b") { |f| f.write attachment.body.decoded }
# create the upload for the user # create the upload for the user
upload = Upload.create_for(user.id, tmp, attachment.filename, File.size(tmp)) upload = Upload.create_for(user.id, tmp, attachment.filename, tmp.size)
if upload && upload.errors.empty? if upload && upload.errors.empty?
# TODO: should use the same code as the client to insert attachments # TODO: should use the same code as the client to insert attachments
raw << "\n#{attachment_markdown(upload)}\n" raw << "\n#{attachment_markdown(upload)}\n"

View File

@ -462,7 +462,7 @@ class ImportScripts::Base
src.close src.close
tmp.rewind tmp.rewind
Upload.create_for(user_id, tmp, source_filename, File.size(tmp)) Upload.create_for(user_id, tmp, source_filename, tmp.size)
ensure ensure
tmp.close rescue nil tmp.close rescue nil
tmp.unlink rescue nil tmp.unlink rescue nil