我使用基于 amazon s3 的单独远程存储来存储图像。通过 activeadmin 更新记录我在图像更新过程中遇到了未知错误。这不是堆栈跟踪的rails错误,而是在舞台环境中发生了某种超时。
配置/初始化程序/carrierwave.rb
CarrierWave.configure do |config|
config.storage = :fog
config.fog_credentials = {
:provider => 'AWS',
:aws_access_key_id => APP['s3']['key'],
:aws_secret_access_key => APP['s3']['secret'],
}
config.fog_directory = 'mdfile'
config.fog_public = false
config.fog_authenticated_url_expiration = 5
config.cache_dir = File.join(Rails.root, 'tmp', 's3', Rails.env)
end
应用程序/上传程序/news_image_uploader.rb
class NewsImageUploader < Mdfile::BaseUploader
include CarrierWave::MiniMagick
process :resize_to_fill => [150, 112]
process convert: 'png'
def extension_white_list
APP['upload']['image_white_list']
end
def fog_public
true
end
def filename
"image.png" if original_filename
end
end
应用程序/上传程序/mdfile/base_uploader.rb
module Mdfile
class BaseUploader < CarrierWave::Uploader::Base
before :store, :remember_cache_id
before :cache, :remove_old_file_before_cache
def remember_cache_id(new_file)
@cache_id_was = cache_id
end
def remove_old_file_before_cache(new_file)
remove! unless blank?
end
def store_dir
"uploads/#{Rails.env}/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def filename
if original_filename
@name ||= Digest::MD5.hexdigest(File.dirname(current_path))
"#{@name}.#{file.extension}"
end
end
end
end
分配给模型的所有图像(新闻、文章)都存储在远程 s3 上的特殊路径上:uploads/stage/article/image/691/image.png
我进行了研究并使用 EXCON_DEBUG=true 运行 rails 以记录 s3 和我的主机之间的请求和响应。已确定
关于创建新记录:
Excon 发送一个 PUT 请求转储在下面
excon.request {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0", "Content-Length"=>37593, "Content-Type"=>"image/jpeg", "x-amz-acl"=>"public-read", "Date"=>"Wed, 14 Aug 2013 08:49:52 +0000", "Authorization"=>"REDACTED", "Host"=>"mdfile.s3.amazonaws.com:443"}, :idempotent=>true, :instrumentor_name=>"excon", :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"mdfile.s3.amazonaws.com", :path=>"/uploads%2Fdevelopment%2Fnews%2Fimage%2F692%2Fimage.png", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>"REDACTED", :instrumentor=>Excon::StandardInstrumentor, :body=>#<File:/local/path/to/cached/file/20130814-1249-6113-6726/Reaktor.jpg>, :expects=>200, :method=>"PUT", :retries_remaining=>4 }
excon.response {:body=>"", :headers=>{ "Date"=>"Wed, 14 Aug 2013 08:49:53 GMT", "Content-Length"=>"0", "Server"=>"AmazonS3"}, :status=>200, :remote_ip=>"[XXX.XXX.XXX.XXX]"}
我削减了一些私人和无用的领域。
关于更新现有记录:
Excon 发送一个删除旧图像的 DELETE 请求,然后它发送 GET-request for path="/" (wtf!!) 并陷入 GET-requests 和成功响应的无限循环。
excon.request {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0", "Date"=>"Wed, 14 Aug 2013 08:56:47 +0000", "Authorization"=>"REDACTED", "Host"=>"mdfile.s3.amazonaws.com:443"}, :idempotent=>true, :instrumentor_name=>"excon", :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"mdfile.s3.amazonaws.com", :path=>"/uploads%2Fdevelopment%2Fnews%2Fimage%2F692%2Fimage.png", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>"REDACTED", :family=>0, :expects=>204, :method=>"DELETE", :retries_remaining=>4, :connection=>#<Excon::Connection:b2ee900 @data={:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0"}, :idempotent=>false, :instrumentor_name=>"excon", :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>nil, :instrumentor=>Excon::StandardInstrumentor, :family=>0} @socket_key="s3.amazonaws.com:443">, :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>nil, :instrumentor=>Excon::StandardInstrumentor, :family=>0} @socket_key="s3.amazonaws.com:443">>>>>}
excon.response {:body=>"", :headers=>{"Date"=>"Wed, 14 Aug 2013 08:56:48 GMT", "Server"=>"AmazonS3"}, :status=>204, :remote_ip=>"[XXX.XXX.XXX.XXX]"}
excon.request {:chunk_size=>1048576, :connect_timeout=>60, :headers=>{"User-Agent"=>"fog/1.9.0", "Date"=>"Wed, 14 Aug 2013 08:56:48 +0000", "Authorization"=>"REDACTED", "Host"=>"s3.amazonaws.com:443"}, :idempotent=>true, :instrumentor_name=>"excon", :mock=>false, :nonblock=>true, :read_timeout=>60, :retry_limit=>4, :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>"REDACTED", :instrumentor=>Excon::StandardInstrumentor, :family=>0, :expects=>200, :method=>"GET", :url=>"s3.amazonaws.com", :ssl_verify_peer=>true, :uri_parser=>URI, :write_timeout=>60, :host=>"s3.amazonaws.com", :path=>"/", :port=>"443", :query=>nil, :scheme=>"https", :user=>nil, :password=>nil, :instrumentor=>Excon::StandardInstrumentor, :family=>0} @socket_key="s3.amazonaws.com:443">}
excon.response {:body=>"", :headers=>{"Date"=>"Wed, 14 Aug 2013 08:56:50 GMT", "Content-Type"=>"application/xml", "Transfer-Encoding"=>"chunked", "Server"=>"AmazonS3"}, :status=>200, :remote_ip=>"[XXX.XXX.XXX.XXX]"}
所以我可以通过 kill -9 在 localhost 上停止 rails 进程
然后我澄清了这种行为发生在调用 CarrierWave 逻辑的模型(News、Articles...)的 update_attribute(s) 方法中。
问题:为什么carrierwave/fog会发出奇怪的GET请求并滚动到无限循环
- 导轨 3.2.14
- 活动管理员 0.5.1
- 继承资源 1.4.1
- 载波 0.8.0
- 雾 1.9.0
- excon 0.20.1
更新:我发现如果我在更新属性之前使用 nil 值更新上传者的列(在我的情况下为“图像”),而不是正确的 PUT 请求被发送到 s3。所以activeadmin控制器的错误修复代码是:
controller do
def update
resource_object = resource_class
@object = resource_object.find(params[:id])
object_sym = resource_class.to_s.downcase.to_sym
@object.update_column(:image, nil) if @object.respond_to?(:image) && params[object_sym][:image].present?
update!
end
end
但问题仍然是热门话题。