Paperclip, Delayed Job, S3, Heroku - дизайн для отложенной обработки конфиденциальных загруженных файлов: db или s3? - PullRequest
5 голосов
/ 12 декабря 2011

Мне нужен отзыв о дизайне для загрузки и отложенной обработки файла с использованием heroku, скрепки, отложенной работы и, при необходимости, s3. Части этого были обсуждены в других местах, но я не мог найти полное обсуждение нигде.

Описание задачи:

  1. Загрузить файл (используя скрепку для s3 / db на heroku). Файл должен быть закрытым, поскольку он содержит конфиденциальные данные.
  2. Файл очереди на обработку (отложенное задание)
  3. Задание запускается в очереди
  4. Файл получен (из s3 / db), и обработка завершена
  5. Файл удален (из s3 / db)

Поскольку я использую отложенное задание, мне нужно выбрать между сохранением файла в базе данных или на s3. Я предполагаю, что о сохранении файла на веб-сервере не может быть и речи, так как я использую heroku и отложенную работу. Загрузка файлов на s3 занимает много времени. Но хранить файлы в БД дороже. В идеале мы бы хотели, чтобы обработка завершилась как можно быстрее.

Каков наиболее распространенный шаблон проектирования? Хранить файлы на с3? Хранить файлы в БД? Любые конкретные рекомендуемые гемы, используемые для извлечения и обработки файлов, хранящихся в s3 (aws-s3? S3?)?

Ответы [ 2 ]

4 голосов
/ 15 декабря 2011

У Heroku есть тайм-аут 30 секунд на любой запрос к серверу (научился нелегко), поэтому обязательно хранить файлы на s3.

Попробуйте carrierwave ( carrierwave railscasts ) вместо скрепки, так как я предпочитаю добавить дополнительных помощников, которые есть на борту, а также ряд замечательных плагинов, таких как carrierwave_direct для загрузки больших файлов в s3, которые прекрасно интегрируются с carrierwave.

Delayed_job (railscasts - delayed_job ) будет отлично работать для удаления файлов из s3 и любой другой фоновой обработки, которая может потребоваться.

В моем файле gem содержится следующее:

gem 'delayed_job'

gem "aws-s3", :require => 'aws/s3'

gem 'fog'

gem 'carrierwave'

gem 'carrierwave_direct'

fog gem - это хороший способ собрать всю информацию о вашей учетной записи в одном месте и настроить все довольно хорошо. Для AWS gem how-to , хороший ресурс.

Вот пример контроллера при отправке формы для загрузки (есть определенно лучшие способы сделать это, но для иллюстративных целей)

def create
    @asset = Asset.new(:description => params[:description], :user_id => session[:id], :question_id => @question.id)
    if @asset.save && @asset.update_attributes(:file_name => sanitize_filename(params[:uploadfile].original_filename, @asset.id))
        AWS::S3::S3Object.store(sanitize_filename(params[:uploadfile].original_filename, @asset.id), params[:uploadfile].read, 'bucket_name', :access => :private, :content_type => params[:uploadfile].content_type)
            if object.content_length.to_i < @question.emailatt.to_i.megabytes && object.content_length.to_i < 5.megabytes
                url = AWS::S3::S3Object.url_for(sanitize_filename(params[:uploadfile].original_filename, @asset.id), 'bucket_name')
                if @asset.update_attributes(:download_link => 1)
                    if Usermailer.delay({:run_at => 5.minutes.from_now}).attachment_user_mailer_download_notification(@asset, @question)
                        process_attachment_user_mailer_download(params[:uploadfile], @asset.id, 24.hours.from_now, @question.id)
                        flash[:notice] = "Thank you for the upload, we will notify this posts author"
                    end
                end
            end
    else
        @asset.destroy
        flash[:notice] = "There was an error in processing your upload, please try again"
        redirect_to(:controller => "questions", :action => "show", :id => @question.id)
    end
end


private

    def sanitize_filename(file_name, id)
        just_filename = File.basename(file_name)
        just_filename.sub(/[^\w\.\-]/,'_')
        new_id = id.to_s
        new_filename = "#{new_id}" + just_filename
    end

    def delete_process(uploadfile, asset_id, time, question_id)
        asset = Asset.find(:first, :conditions => ["id = ?", asset_id])
        if delete_file(uploadfile, asset_id, time) && asset.destroy
            redirect_to(:controller => "questions", :action => "show", :id => question_id)
        end
    end


def process_attachment_user_mailer_download(uploadfile, asset_id, time, question_id)
        asset = Asset.find(:first, :conditions => ["id = ?", asset_id])
        if delete_file(uploadfile, asset_id, time) && @asset.delay({:run_at => time}).update_attributes(:download_link => 0)
            redirect_to(:controller => "questions", :action => "show", :id => question_id)
        end
    end

    #S3 METHODS FOR CREATE ACTION

    #deletes the uploaded file from s3
    def delete_file(uploadfile, asset_id, time)
        AWS::S3::S3Object.delay({:run_at => time}).delete(sanitize_filename(uploadfile.original_filename, asset_id), 'bucket_name')
    end

Много ненужного кода, я знаю (написал это, когда я начинал с Rails). Надеемся, что это даст некоторое представление о процессах, связанных с написанием этого типа приложения. Надеюсь, это поможет.

3 голосов
/ 31 января 2012

Я со своей стороны использую:

  • Задержка
  • Скрепка
  • Задержка скрепки , которая загружает исходный файл на S3 и создайте отложенное задание с помощью пользовательской постобработки. Это можете добавить столбец к вашей модели, указав, что файл обрабатываются.

Всего несколько строк для настройки. И вы можете многое сделать с помощью интерполяции скрепок и генераторов.

...