Rails, Paperclip, Direct Upload to S3 - Authenticated URL returns SignatureDoesNotMatch response
rails(?> 3.2.13)
回形针(2.7.4)
aws-sdk(1.8.0)
在使用Paperclip的Rails应用程序中,我有一个名为" Asset"的模型,该模型具有一个名为" upload"的附件(s3_permissions:" private")。
此附件首先直接上传到Amazon S3,然后保存资产。要进行直接上传,我使用了以下gem
通过遵循教程http://www.blitztheory.com/direct-upload-with-s3_direct_upload/
中的说明,https://github.com/waynehoover/s3_direct_upload gem
注意:
本教程中我忽略的一件事是我没有使用类方法copy_and_delete(paperclip_file_path,raw_source)在所需路径中重新创建存储桶中的资产。
我首先从视图中将图像" Mars.gif"上传到Amazon S3,并将其与我的Asset对象关联。该图像已成功上传到存储桶中,资产也已成功保存。我正在查看其详细信息,并尝试使用图像的源URL打开附件" Mars.gif":
http://s3.amazonaws.com/mm_tom_test/uploads/1390421005820-yff5taw7kgf-da8b488d45d747deb206977d29e11005/Mars.gif?AWSAccessKeyId=AKIAIMKHM4EATOHUAQ3Q
我自己解决了这个问题,并回答了我自己的问题,以防其他人最终遇到上述问题。
S3DirectUpload gem在其
如果将该键保存为应用程序的数据库中的相同键,然后使用
从Amazon S3返回。
但是,如果我们先清理最初收到的密钥,则可以通过以下方式将其保存到应用程序的数据库中:
然后在访问时生成的到期URL允许成功访问资源。
万一有人遇到这个问题,我在这里给出我模型的工作代码片段。其他代码片段可以在我上面的评论中找到。
/app/models/asset.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | class Asset < ActiveRecord::Base include S3Decider attr_accessible :upload, :upload_file_name, :upload_content_type, upload_file_size, :upload_updated_at attr_accessible :key paperclip_options_for_upload = paperclip_options_for_upload.merge( path:":key", url:":s3_conditional_url", s3_url_options: lambda { |model| { response_content_type: model.upload_content_type, response_content_disposition:"inline" } } ) has_attached_file :upload, paperclip_options_for_upload def key=(key) return if key.blank? # S3DirectUpload receives the Amazon S3 bucket object's key # as encoded and prefixed by a forward slash.For e.g. # /uploads%2F1390554749261-nuflsns5cn-0de4e0f6e495e02bc5ee0c853d56b95f%2Fflower-3.jpeg # Sanitizing it here else programmatically accessing the bucket object # corresponding to the key prefixed with"/" shall throw a No such key # exception. sanitized_key = key.sub(%r{^/},'') decoded_key = CGI.unescape(sanitized_key) write_attribute(:key, decoded_key) end end |
也在寻找解决方案时,我遇到了以下拉动请求#769,其中确切提到了我所面临的问题。
当我使用回形针(2.7.4)时,其S3存储区不包含在拉取请求中所做的更改。我通过检查rvm目录下本地安装的gem中的源代码进行了验证。因此,我更改了上述代码具有以下内容:
/config/initializers/paperclip.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | Paperclip::ASSET_EXPIRATION_TIME = 3600.seconds Paperclip.interpolates(:key) do |attachment, style| attachment.instance.key end Paperclip.interpolates(:s3_conditional_url) do |attachment, style| attachment.expiring_url(Paperclip::ASSET_EXPIRATION_TIME, style) end module Paperclip::Storage::S3 def public_url(style_name = default_style) if path "http://#{s3_host_name}/#{bucket_name}/#{path(style_name)}" end end def expiring_url(time = Paperclip::ASSET_EXPIRATION_TIME, style_name = default_style) if path # Reference: https://github.com/thoughtbot/paperclip/pull/769 base_options = { :expires => time, :secure => use_secure_protocol?(style_name) } s3_object(style_name).url_for(:read, base_options.merge(s3_url_options)).to_s end end # Reference: https://github.com/thoughtbot/paperclip/pull/769 def s3_url_options s3_url_options = @options[:s3_url_options] || {} s3_url_options = s3_url_options.call(instance) if s3_url_options.is_a?(Proc) s3_url_options end end |
谢谢,
吉涅什