我有一个rails应用程序,允许用户直接将与帖子相关的图像上传到S3,然后运行图像处理“延迟”作业来调整它的大小。使用Web浏览器时一切运行良好,但最近我正在编写一些db填充任务,但是当我尝试保存图像及其相关模型时,此错误显示:ArgumentError: key may not be blank
。知道为什么会发生这种情况会很棒!!
populate.rake代码的片段:
post = Post.new(user: user)
((rand*5).floor + 1).times do
## Here, you will need to upload the file to S3, get the direct_upload_url then save it for img.direct_upload_url
# Upload to S3, then get the direct_upload_url
file=File.open(Dir.glob(File.join(Rails.root, 'sampleimages/posts', '*')).sample)
s3_obj = S3_BUCKET.objects["direct_uploads/#{Time.now.to_i}/#{File.basename(file)}"]
puts " Selected file: #{File.basename(file)}"
puts " --> Starting upload"
s3_obj.write(file)
#s3_obj.acl= :public_read
obj_url = ""
while obj_url.blank?
obj_url = s3_obj.url_for(:read)
sleep(3)
end
puts " --> Loop completed with obj_url = #{obj_url}"
img = post.images.build(direct_upload_url: obj_url.to_s)
# puts "url_for #{obj_url}"
puts "Image uploaded: #{s3_obj.key} URL: #{img.direct_upload_url}\n"
# The below code is used for local file storage
#img.image_file = File.open(Dir.glob(File.join(Rails.root, 'sampleimages/posts', '*')).sample)
end
post.save!
end
错误显示在post.save!
。
以下是Image.rb
:
## S3_direct_upload post processing!
before_create :set_upload_attributes
### setting the image_to_process of this image.
before_create :inc_images_to_process
after_create :queue_processing
def direct_upload_url=(escaped_url)
write_attribute(:direct_upload_url, (CGI.unescape(escaped_url) rescue nil))
end
# Determines if file requires post-processing (image resizing, etc)
# All files should be processable in my case, where only images can be stored.
def post_process_required?
%r{^(image|(x-)?application)/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$}.match(image_file_content_type).present?
end
# Final upload processing step
def self.transfer_and_cleanup(id)
begin
## This will raise exception, need to catch this.
image = Image.find_by_id(id)
## Check if the image still exists when this is running, if not, then just skip this and minus one from post
if image.nil? || image.processed
## Something's wrong, either the image is not present or the image is already processed
Delayed::Worker.logger.debug "ERROR: Image with id: #{id} Not Found. This file will still up on aws temp!"
## The file is not here anymore.
## Ask the post to recalculate how many images it actually has!
if image.present? && image.processed
direct_upload_url_data = DIRECT_UPLOAD_URL_FORMAT.match(image.direct_upload_url)
S3_BUCKET.objects[direct_upload_url_data[:path]].delete
end
else
## With this match, path and filename will be extracted.
direct_upload_url_data = DIRECT_UPLOAD_URL_FORMAT.match(image.direct_upload_url)
if image.post_process_required?
image.image_file = URI.parse(URI.escape(image.direct_upload_url))
else
# Somethings's wrong???!?!?!? It should be images!
paperclip_file_path = "images/uploads/#{id}/original/#{direct_upload_url_data[:filename]}"
S3_BUCKET.objects[paperclip_file_path].copy_from(direct_upload_url_data[:path])
end
image.processed = true
if image.save
## To unset the image_to_process field of its parent - the Post
if image.imageable.class.to_s == "Post"
# logger.debug "I am here!!!"
post = image.imageable
post.images_to_process -= 1
post.save!
end
Delayed::Worker.logger.debug "Image:#{id}:transfer_and_cleanup: It is now saved"
else
Delayed::Worker.logger.debug "Image:#{id}:transfer_and_cleanup: ERROR Occurs: #{image.errors.full_messages}"
end
### End of image.save
## Delete the temp file.
Delayed::Worker.logger.debug "Image:#{id}:transfer_and_cleanup: direct_upload_url: #{direct_upload_url} is going to deleted"
S3_BUCKET.objects[direct_upload_url_data[:path]].delete
end
## end of image.present? loop
end
end ## End of transfer_and_cleanup
# Set attachment attributes from the direct upload
# @note Retry logic handles S3 "eventual consistency" lag.
def set_upload_attributes
logger.debug "You are now in set_upload_attributes"
tries ||= 5
direct_upload_url_data = DIRECT_UPLOAD_URL_FORMAT.match(direct_upload_url)
direct_upload_head = S3_BUCKET.objects[direct_upload_url_data[:path]].head
self.image_file_file_name = direct_upload_url_data[:filename]
self.image_file_file_size = direct_upload_head.content_length
self.image_file_content_type = direct_upload_head.content_type
self.image_file_updated_at = direct_upload_head.last_modified
## Rescue the S3 Errors here
rescue AWS::S3::Errors::NoSuchKey => e
tries -= 1
if tries > 0
sleep(3)
retry
else
false
end
end
# Queue file processing
def queue_processing
Image.delay.transfer_and_cleanup(id)
Delayed::Worker.logger.debug "queue_processing: Image #{id} added in the queue. At "
end
def inc_images_to_process
# Increase the image required to process in Post.
if self.imageable.class.to_s == "Post"
post = self.imageable
post.inc_images_to_process
Delayed::Worker.logger.debug "inc_images_to_process: Post #{post.id} new images_to_process is now: #{post.images_to_process}"
end
end
错误消息是:
rake aborted!
ArgumentError: key may not be blank
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/s3/client.rb:384:in `validate!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/s3/client.rb:390:in `validate_key!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/s3/client.rb:542:in `block (2 levels) in object_method'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/s3/client.rb:1563:in `block (2 levels) in <class:V20060301>'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:560:in `build_request'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:491:in `block (3 levels) in client_request'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/response.rb:175:in `call'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/response.rb:175:in `build_request'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/response.rb:114:in `initialize'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:203:in `new'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:203:in `new_response'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:490:in `block (2 levels) in client_request'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:391:in `log_client_request'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:477:in `block in client_request'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:373:in `return_or_raise'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/core/client.rb:476:in `client_request'
(eval):3:in `head_object'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/aws-sdk-v1-1.56.0/lib/aws/s3/s3_object.rb:296:in `head'
/Users/quindici/Documents/Career/QUIN CREATIVES/Local-say/Local-say-System/app/models/image.rb:134:in `set_upload_attributes'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:377:in `_run__4088547230130556858__create__callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:303:in `create_record'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/timestamp.rb:57:in `create_record'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/persistence.rb:466:in `create_or_update'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:299:in `block in create_or_update'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:383:in `_run__4088547230130556858__save__callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:299:in `create_or_update'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/persistence.rb:106:in `save'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/validations.rb:51:in `save'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:32:in `save'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:270:in `block (2 levels) in save'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:270:in `block in save'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:281:in `rollback_active_record_state!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:269:in `save'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/associations/has_many_association.rb:39:in `insert_record'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/autosave_association.rb:348:in `block in save_collection_association'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/autosave_association.rb:339:in `each'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/autosave_association.rb:339:in `save_collection_association'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/autosave_association.rb:183:in `block in add_autosave_association_callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/autosave_association.rb:153:in `instance_eval'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/autosave_association.rb:153:in `block in define_non_cyclic_method'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:383:in `_run__690630312330398441__update__callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:307:in `update_record'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/timestamp.rb:70:in `update_record'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/persistence.rb:466:in `create_or_update'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:299:in `block in create_or_update'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:413:in `_run__690630312330398441__save__callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/callbacks.rb:299:in `create_or_update'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/persistence.rb:128:in `save!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/validations.rb:57:in `save!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/attribute_methods/dirty.rb:41:in `save!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `block in save!'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:209:in `transaction'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
/Users/quindici/.rvm/gems/ruby-2.0.0-p247@railstutorial_rails_4_0/gems/activerecord-4.0.0/lib/active_record/transactions.rb:275:in `save!'
/Users/quindici/Documents/Career-System/lib/tasks/populate.rake:139:in `block (4 levels) in <top (required)>'
/Users/quindici/Documents/Career-System/lib/tasks/populate.rake:56:in `times'
/Users/quindici/Documents/Career-System/lib/tasks/populate.rake:56:in `block (3 levels) in <top (required)>'
/Users/quindici/Documents/Career-System/lib/tasks/populate.rake:31:in `times'
/Users/quindici/Documents/Career-System/lib/tasks/populate.rake:31:in `block (2 levels) in <top (required)>'
Tasks: TOP => db:db_populate
答案 0 :(得分:1)
感谢所有帮助,我发现了问题。
错误实际上是因为访问对象时未提供密钥。发生这种情况是因为上传网址与正则表达式的格式不同,因此&#34;键&#34;从direct_upload_url中提取的是nil。因此,当Image
对象试图在set_upload_attributes
中保存文件详细信息时,S3_BUCKET.objects []没有键,因此ArgumentError!
感谢您阅读!