使用Paperclip将数千个图片上传到S3

3

我有大约16,000张图片需要上传到亚马逊。目前,它们在我的本地文件系统中。我想使用Paperclip将它们上传到S3,但我不想先将它们上传到我的服务器。我正在使用Heroku,他们限制了Slug大小。

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

3个回答

4
您可以配置您的应用程序在开发中使用Amazon S3作为Paperclip存储(请参考我的示例),并使用类似于以下的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秒)。我还有一个问题,就是paperclip在文件名中使用图像的id。因此,即使我运行了您提到的rake任务,在生产中的id也不会与开发中的id匹配。 - Chris
在这种情况下,您可以使用文件上传器将文件上传到类似于Dropbox(甚至是临时S3存储桶)的位置,然后从您的Heroku应用程序运行此rake任务(传递远程链接),以将它们移动到您的Paperclip存储桶/关联它们与您的模型。 - David
谢谢Johnny。我们也尝试了这种方法,但在Heroku上通过FTP访问文件时遇到了问题。最终我们在本地上传到了Paperclip,并将所有图像URL输出到文本文件中,然后将该文件部署到生产环境并读取所有图像URL。虽然这是一个令人不快的hack,但确实起作用了。感谢你的建议。 - Chris

1

0
很棒的回答Johnny Grass和很好的问题Chris。我在本地机器、Heroku、paperclip和s3上有几百个tif文件。一些tiff文件大于100MB,因此让heroku关注那么长时间需要延迟作业和一些额外的工作。由于这是一个大多数情况下只需一次批处理过程(从每个批处理中创建5种不同的图像形式,每种形式有5个上传),所以rake任务的想法非常适合。在这里,以防有帮助,是我创建的rake任务,假设像Johnny写的那样,您的开发数据库具有当前数据(使用pg备份获取新的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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接