s3_direct_upload作为rake任务,url无效 - 如何直接设置direct_upload_url

时间:2014-11-30 05:29:55

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

我通过Web UI使用带有PaperClip的s3_direct_upload,这一切都运行良好。

但是,我有一个rake任务,正在寻找要在后台上传的文件,并使用相同的进程加载作业,这当前是错误的:

ActiveRecord::RecordInvalid: Validation failed: Direct upload url can't be blank, Direct upload url is invalid

这并不意外,因为后台任务没有使用javascript工具上传文件。

如何设置正确的direct_upload_url以便现有处理可以继续?

1 个答案:

答案 0 :(得分:0)

唯一有效的方法是基本上复制直接上传的内容(作为间接上传)并使其成为条件。一旦我仔细考虑了代码的作用,就会变得更加明显。

对于direct_upload_url,模式匹配只有一点点,这在某种程度上取决于你的情况

下面的

是我的模型的相关部分,它们已被更改为处理这两种情况

  BUCKET_NAME         = ENV['AWS_BUCKET'] 
  UPLOAD_BUCKET_NAME  = ENV['UPLOAD_BUCKET']
  DIRECT_UPLOAD_URL_FORMAT = %r{\Ahttps:\/\/#{BUCKET_NAME}\.s3\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\z}.freeze
  INDIRECT_UPLOAD_URL_FORMAT = %r{\Ahttps:\/\/#{UPLOAD_BUCKET_NAME}\.s3\.amazonaws\.com\/(?<filename>.+)\z}.freeze

  validates :direct_upload_url, presence: true, format: { with: DIRECT_UPLOAD_URL_FORMAT }, if: :direct_upload?
  validates :direct_upload_url, presence: true, format: { with: INDIRECT_UPLOAD_URL_FORMAT }, if: :indirect_upload?

  # attributes have already been set - file is already up on S3 
  before_create :set_upload_attributes, if: :direct_upload?
  after_create :queue_finalize_and_cleanup

...

  def self.finalize_and_cleanup(id)
    import = Import.find(id)
    if import.indirect_upload?
      direct_upload_url_data = INDIRECT_UPLOAD_URL_FORMAT.match(import.direct_upload_url)
    else
      direct_upload_url_data = DIRECT_UPLOAD_URL_FORMAT.match(import.direct_upload_url)
    end
    s3 = AWS::S3.new
    if import.post_process_required?
      import.import_file = URI.parse(URI.escape(import.direct_upload_url))
    else
      paperclip_file_path = "imports/import_files/#{id}/original/#{direct_upload_url_data[:filename]}"
      if import.indirect_upload?
        # coming from a different bucket, and there is no PATH variable 
        s3.buckets[BUCKET_NAME].objects[paperclip_file_path].copy_from(direct_upload_url_data[:filename], { bucket_name: UPLOAD_BUCKET_NAME })
      else
        s3.buckets[BUCKET_NAME].objects[paperclip_file_path].copy_from(direct_upload_url_data[:path])
      end
    end

    import.processed = true
    import.state = 'Queued'
    import.save
    import.process

    if import.indirect_upload?
      s3.buckets[UPLOAD_BUCKET_NAME].objects[direct_upload_url_data[:filename]].delete
    else
      s3.buckets[BUCKET_NAME].objects[direct_upload_url_data[:path]].delete
    end

  end