2009-11-01 6 views
1

J'utilise une application Rails en utilisant Paperclip pour prendre en charge les pièces jointes et le redimensionnement de l'image, etc. L'application est actuellement hébergée sur EngineYard cloud, et toutes les pièces jointes sont stockées dans leur EBS. Penser à utiliser S3 pour gérer toutes les pièces jointes Paperclip.Matrice de données de EC2 à S3?

Quelqu'un connaît-il un moyen sûr et bon pour cette migration? Merci beaucoup!

Répondre

3

Vous pouvez travailler une tâche de rake qui répète sur vos pièces jointes et pousse chacune à S3. Je l'ai utilisé un moment avec attachment_fu - ne serait pas trop différent. Cela utilise la gemme aws-s3.

Fondamentalement, le processus est le suivant: 1. Sélectionnez les fichiers de la base de données qui doivent être déplacés 2. Poussez-les à S3 3. Base de données de mise à jour pour refléter le fait que le fichier n'est stocké plus localement (cette façon, vous pouvez faire les par lots et ne pas avoir à se soucier de pousser deux fois le même fichier).

@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 
3

Je me suis retrouvé dans la même situation et a pris le code de bensie et fait fonctionner pour moi - c'est ce que je suis venu avec:

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? 

Bien sûr, si vous avez plusieurs modèles vous seront besoin d'ajuster au besoin ...

Questions connexes