Paperclip,Delayed Job,S3,Heroku - 设计用于延迟处理敏感上传文件:db或s3?

时间:2011-12-12 18:43:54

标签: heroku amazon-s3 paperclip delayed-job

我需要使用heroku,回形针,延迟作业以及必要时s3对文件上传和延迟处理的设计进行反馈。部分内容已在其他地方进行过讨论,但我无法在任何地方找到完整的讨论。

任务说明:

  1. 上传文件(使用paperclip到heroku上的s3 / db)。文件必须是私有的,因为它包含敏感数据。
  2. 用于处理的队列文件(延迟作业)
  3. 作业在队列中运行
  4. 检索文件(从s3 / db开始),处理完成
  5. 删除文件(来自s3 / db)
  6. 由于我使用延迟作业,我必须决定将文件存储在数据库中还是存储在s3上。我假设将文件存储在Web服务器上是不可能的,因为我正在使用heroku和延迟工作。将文件上传到s3需要很长时间。但是,在db中存储文件更加昂贵。理想情况下,我们希望处理尽快完成。

    更常见的设计模式是什么?在s3上存储文件?将文件存储在db中?用于检索和处理存储在s3中的文件的任何特定推荐宝石(aws-s3?s3?)?

2 个答案:

答案 0 :(得分:4)

Heroku在任何服务器请求上都有30秒的超时(通过艰难的方式学习),所以绝对必须在s3上存储文件。

尝试使用carrierwavecarrierwave railscasts)代替回形针,因为我更喜欢添加的辅助工具,还有一些很棒的插件,比如carrierwave_direct用于将大文件上传到s3 ,与carrierwave很好地集成。

Delayed_job(railscasts - delayed_job)可以很好地删除s3中的文件以及可能需要的任何其他后台处理。

我的宝石文件包含以下内容:

gem 'delayed_job'

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

gem 'fog'

gem 'carrierwave'

gem 'carrierwave_direct'

雾宝石是一种很好的方式,可以将您的所有帐户信息放在一个地方,并很好地设置所有内容。对于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时编写了这个代码)。希望它能让您对编写此类应用程序所涉及的过程有所了解。希望它有所帮助。

答案 1 :(得分:3)

就我而言,我正在使用:

  • Delayed Job
  • Paperclip
  • 上传原始文件的
  • Delayed Paperclip 在S3上,使用自定义后期处理创建延迟作业。它 可以为模型添加一个列,说明该文件正在存在 处理。

只需几行即可设置。你可以用回形针插值和生成器做很多事情。