我通过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以便现有处理可以继续?
答案 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