1

ファイルの添付や画像のサイズ変更などを処理するために、Paperclip を使用して Rails アプリを実行しています。このアプリは現在、EngineYard クラウドでホストされており、すべての添付ファイルは EBS に保存されています。すべての Paperclip 添付ファイルを処理するために S3 を使用することを考えています。

この移行のための適切で安全な方法を知っている人はいますか? どうもありがとう!

4

2 に答える 2

3

添付ファイルを繰り返し処理し、それぞれを S3 にプッシュする rake タスクを作成できます。これをしばらく前に attachment_fu で使用しましたが、それほど違いはありません。これは aws-s3 gem を使用します。

基本的なプロセスは次のとおりです。 1. 移動する必要があるファイルをデータベースから選択します。 2. それらを S3 にプッシュします。 3. データベースを更新して、ファイルがローカルに保存されなくなったことを反映します (この方法では、バッチで実行でき、同じファイルを 2 回プッシュすることを心配する必要があります)。

@attachments = Attachment.stored_locally
@attachments.each do |attachment|

  base_path = RAILS_ROOT + '/public/assets/'
  attachment_folder = ((attachment.respond_to?(:parent_id) && attachment.parent_id) || attachment.id).to_s
  full_filename = File.join(base_path, ("%08d" % attachment_folder).scan(/..../), attachment.filename)
  require 'aws/s3'

  AWS::S3::Base.establish_connection!(
    :access_key_id        => S3_CONFIG[:access_key_id],
    :secret_access_key    => S3_CONFIG[:secret_access_key]
  )

  AWS::S3::S3Object.store(
    'assets/' + attachment_folder + '/' + attachment.filename,
    File.open(full_filename),
    S3_CONFIG[:bucket_name],
    :content_type => attachment.content_type,
    :access => :private
  )

  if AWS::S3::Service.response.success?
    # Update the database
    attachment.update_attribute(:stored_on_s3, true)

    # Remove the file on the local filesystem
    FileUtils.rm full_filename

    # Remove directory also if it is now empty
    Dir.rmdir(File.dirname(full_filename)) if (Dir.entries(File.dirname(full_filename))-['.','..']).empty?
  else
    puts "There was a problem uploading " + full_filename
  end
end
于 2009-11-01T22:17:14.390 に答える
3

私は同じ状況に陥り、bensie のコードを取得して自分で動作させるようにしました - これが私が思いついたものです:

require 'aws/s3'

# Ensure you do the following:
#   export AMAZON_ACCESS_KEY_ID='your-access-key'
#   export AMAZON_SECRET_ACCESS_KEY='your-secret-word-thingy'
AWS::S3::Base.establish_connection!


@failed = []
@attachments = Asset.all # Asset paperclip attachment is: has_attached_file :attachment....
@attachments.each do |asset|
  begin
    puts "Processing #{asset.id}"
    base_path = RAILS_ROOT + '/public/'
    attachment_folder = ((asset.respond_to?(:parent_id) && asset.parent_id) || asset.id).to_s
    styles = asset.attachment.styles.keys
    styles << :original
    styles.each do |style|
      full_filename = File.join(base_path, asset.attachment.url(style, false))


      AWS::S3::S3Object.store(
        'attachments/' + attachment_folder + '/' + style.to_s + "/" + asset.attachment_file_name,
        File.open(full_filename),
        "swellnet-assets",
        :content_type => asset.attachment_content_type,
        :access => (style == :original ? :private : :public_read)
      )

      if AWS::S3::Service.response.success?        
        puts "Stored #{asset.id}[#{style.to_s}] on S3..."
      else
        puts "There was a problem uploading " + full_filename
      end
    end
  rescue
    puts "Error with #{asset.id}"
    @failed << asset.id
  end
end

puts "Failed uploads: #{@failed.join(", ")}" unless @failed.empty?

もちろん、複数のモデルがある場合は、必要に応じて調整する必要があります...

于 2010-02-17T10:12:01.877 に答える