使用Paperclip将数千张图像上传到S3

时间:2011-06-23 22:31:35

标签: ruby-on-rails amazon-s3 paperclip

我正在尝试将大约16,000张图片上传到亚马逊。现在,他们在我的本地文件系统上。我想使用Paperclip将它们上传到S3,但我不想先将它们上传到我的服务器。我正在使用Heroku并且它们限制了slug尺寸。

有没有办法使用rake任务通过Paperclip将图像直接从我的本地文件系统上传到S3?

3 个答案:

答案 0 :(得分:3)

您可以将应用配置为在开发中使用Amazon S3进行回形针存储(see my example),并使用如下的rake任务上传文件:

假设您的图片文件夹位于your_app_folder/public/images,您可以创建类似于此的rake任务。

namespace :images do
  desc "Upload images."
  task :create => :environment do
    @images = Dir["#{RAILS_ROOT}/public/images/*.*"]
    for image in @images
      MyModel.create(:image => File.open(image))
    end
  end
end

答案 1 :(得分:1)

是。我在我的第一个个人Rails项目上做了类似的事情。这是以前的SO问题(Paperclip S3 download remote images),其答案链接到我很久以前找到答案的位置(http://trevorturk.com/2008/12/11/easy-upload-via-url-with-paperclip/)。

答案 2 :(得分:0)

很棒的回答Johnny Grass和很棒的问题Chris。我的本地机器上有几百个tif文件,Heroku,paperclip和s3。一些tiff文件是> 100MB,所以让heroku注意那长期需要的延迟工作和一些额外的工作。由于这是一次大部分时间的批处理过程(每次创建5个不同的图像形式,每次上传5次),因此rake任务的概念非常适合。在这里,如果它有帮助,我创建的rake任务是假设像Johnny写的那样,你的开发数据库有当前数据(使用pg backup来获取新的id)并连接到S3。

我有一个名为“Item”的模型,带有附件“image”。我想检查现有项目是否已有图像,如果没有,则上传新图像。效果是镜像源文件的目录。好的扩展可能是检查日期,看看本地tif是否更新。

# lib/image_management.rake
namespace :images do
  desc 'upload images through paperclip with postprocessing'
  task :create => :environment do

    directory = "/Volumes/data/historicus/_projects/deeplandscapes/library/tifs/*.tif"
    images = Dir[directory]

    puts "\n\nProcessing #{ images.length } images in #{directory}..."

    items_with_errors = []
    items_updated = []
    items_skipped = []

    images.each do |image|
    # find the needed record
      image_basename = File.basename(image)
      id = image_basename.gsub("it_", "").gsub(".tif", "").to_i
      if id > 0
        item = Item.find(id) rescue nil
        # check if it has an image already
        if item
          unless item.image.exists?
            # create the image
            success = item.update_attributes(:image => File.open(image))
            if success
              items_updated << item
              print ' u '
            else
              items_with_errors << item
              print ' e '
            end
          else
            items_skipped << item
            print ' s '
          end
        else
          print "[#{id}] "
        end
      else
        print " [no id for #{image_basename}] "    
      end
    end
    unless items_with_errors.empty?
      puts "\n\nThe following items had errors: "
      items_with_errors.each do |error_image|
        puts "#{error_image.id}: #{error_image.errors.full_messages}"
      end
    end

    puts "\n\nUpdated #{items_updated.length} items."
    puts "Skipped #{items_skipped.length} items."
    puts "Update complete.\n"

  end
end