#ruby-on-rails #amazon-s3 #paperclip #delayed-job #swfupload
#ruby-on-rails #amazon-s3 #скрепка #отложенная работа #swfupload
Вопрос:
Я работаю над приложением rails, в котором пользователь будет загружать большое количество изображений.
Моя текущая настройка: использование SWFUpload для одновременной загрузки нескольких файлов с помощью плагина Paperclip с хранилищем S3. После того, как исходное изображение загружено на S3, Delayed_Job используется для последующей обработки (эскизы и т.д.).
Проблема, с которой я сталкиваюсь, в том, что изображения загружаются с очень низкой скоростью. Я предполагаю, что настройка скрепки по умолчанию заключается в том, что изображение будет передаваться от пользователя на -> мой сервер на -> s3.
Я думал, что могу загружать изображения непосредственно на s3, но я не уверен, как реализовать это с помощью скрепки и последующей обработки. Я не смог найти никаких плагинов или примеров, связанных с этим.
У кого-нибудь есть предложения? Если нет, можете ли вы указать мне правильное направление?
Заранее спасибо!
Тим
Ответ №1:
Я сталкивался с этой же проблемой несколько раз. Я решил эту проблему, создав 2 модели, Image
model и TempImage
model, которая наследуется от Image
model. Для этого в вашей type
таблице должен быть Image
столбец. TempImage
Модель сохраняет изображение локально, затем, когда вы обращаетесь к нему напрямую из Image
модели и сохраняете повторно, оно будет соответствовать тому, что определено в Image
модели, являющейся Amazon S3.
Пример:
# Will save in the database as a TempImage inside the Image table
temp = TempImage.create(:asset => File.new('some_path', 'r'))
# When you find it again through the Image model, it bypasses the type column
# so next time you save it, it is saved as an Image.
amazon = Image.find(temp.id)
amazon.save!
Вот моя отложенная работа:
class MoveToS3Job < Struct.new(:temp_revision_id)
def perform
upload = Image.find(temp_revision_id)
temp_path = File.expand_path("tmp/uploads/#{upload.asset_file_name}", Rails.root)
upload.asset = File.new(temp_path, 'r')
upload.save!
if File.exists?(temp_path) amp;amp; !File.directory?(temp_path)
File.delete(temp_path)
end
rescue ActiveRecord::RecordNotFound
# If the record wasn't found, do some sort of
# error report, but don't keep it in the queue.
end
end
Вот TempImage
модель:
class TempImage < Image
has_attached_file :asset, {
:path => ":rails_root/tmp/uploads/:basename_:updated_at.:extension"
}
end
Затем исходная Image
модель:
class Image < ActiveRecord::Base
# Validations
validates :asset, :presence => true
# Paperclip
has_attached_file :asset, :styles => {
:preview => ['100x100#', :png],
:thumb => ['50x50#', :png]
},
:default_style => :thumb,
:storage => :s3,
:bucket => 'bucket-name',
:s3_credentials => File.expand_path('config/s3.yml', Rails.root),
:path => "photos/:id_partition/:style.:extension"
end
Ваша исходная Image
модель всегда должна содержать вашу постобработку, поскольку это будет выполняться в фоновом режиме.
Вы всегда можете перезаписать некоторые методы, чтобы сделать его немного чище, но это дает вам лучшее представление о том, как это работает и что вам нужно сделать, чтобы оно работало так, как вы хотите.
Ответ №2:
Если вы в конечном итоге выберете путь загрузки непосредственно на S3, который выгружает работу с вашего сервера Rails, пожалуйста, ознакомьтесь с моими примерами проектов:
Пример проекта с использованием Rails 3, Flash и FancyUploader на основе MooTools для загрузки непосредственно на S3: https://github.com/iwasrobbed/Rails3-S3-Uploader-FancyUploader
Пример проекта с использованием Rails 3, Flash / Silverlight / GoogleGears /BrowserPlus и Plupload на основе jQuery для загрузки непосредственно на S3: https://github.com/iwasrobbed/Rails3-S3-Uploader-Plupload
Кстати, вы можете выполнить постобработку с помощью скрепки, используя что-то вроде описания в этом сообщении в блоге:
http://www.railstoolkit.com/posts/fancyupload-amazon-s3-uploader-with-paperclip