带有Paperclip的Rails AWS S3“无法加载资源:服务器响应403禁止”

时间:2014-11-10 05:18:54

标签: ruby-on-rails amazon-web-services amazon-s3 paperclip

首先让我说,我的AWS S3和Paperclip图片上传工作正常。下面的参考日志文件。

我花了太多时间试图跟踪Get Method返回403禁止的问题,看起来似乎是由于在文件名的末尾添加了一个扩展名。

我已经确认我可以通过直接在视图中对html源进行硬编码来连接存储在我的存储桶中的图像,例如http://mybucket_name.s3.amazonaws.com/..../filename。图像显示正常。

以下是代码设置:

我正在使用paperclip.rb

# config/initializers/paperclip.rb
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'

我正在使用aws.yml(利用aws-sdk)

#config/aws.yml
development:
  access_key_id: xxxxxx
  secret_access_key: xxxxxxxxxxxxxxxxx

production:
  access_key_id: xxxxxx
  secret_access_key: xxxxxxxxxxxxxxxx

在我的环境中:

.....

#config/environments/development.rb

# Path to ImageMagick
Paperclip.options[:command_path] = "/ImageMagick"

config.paperclip_defaults = {
  :storage => :s3,
  :s3_credentials => {
  :bucket => 'mybucket_name'
  }
}

....

我的Profile模型没什么特别之处。这是我用于回形针的内容:

....
#paperclip image attachment
has_attached_file :logo_image, :styles => { :medium => "250x250>", :small => "175x175>",  
:thumb => "100x100>" }


# Validate content type
validates_attachment_content_type :logo_image, :content_type => /\Aimage/

# Validate filename
validates_attachment_file_name :logo_image, :matches => [/png\Z/, /jpe?g\Z/, /JPG?\Z/]

validates_attachment_size :logo_image, :less_than => 4.megabytes

....

配置文件控制器

#profiles_controller.rb

....
 def create
@profile = Profile.new(profile_params)

if @profile.save

  flash[:notice] = "Profile has been created."

  redirect_to @profile
else
  flash[:alert] = "Profile has not been created."

  render "new"
end
end

def edit

end

def update
if @profile.update(profile_params)
  redirect_to @profile
  flash[:notice] = "Profile has been updated."     
else
  flash[:alert] = "Profile has not been updated."
  render "edit"
end
end


def destroy
@profile.destroy

flash[:notice] = "Profile has been destroyed."

redirect_to profiles_path
end

private

def profile_params
  params.require(:profile).permit(:id, :firstname, :lastname, :instagram, :company, :website,  
  :street_address, :city, :state, :zipcode, :phone, :logo_image, :address, :latitude,   
  :longitude, 
  :user_id, :user_email_id)
end

def set_profile
  @profile = Profile.find(params[:id])
rescue ActiveRecord::RecordNotFound
  flash[:alert] = "The profile you were looking for could not be found."
  redirect_to profiles_path
end

用户模型(我通过用户模型构建profile_id)

class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :confirmable

has_one :profile, :dependent => :destroy, autosave: true
accepts_nested_attributes_for :profile

after_create :build_profile

has_many :tags


def build_profile
  Profile.create(user: self) 
end

end

表单视图(标注:我没有使用multipart =&gt;“true”)

....

  <%= form_for @profile, :html => {"data-ajax" => false} do |f| %>
                                           <p>&nbsp;</p>

                                           [form code here ]

                                           <div class="row">
                                              <div class="col-md-4">
                                                  <%= f.file_field :logo_image %>

                                              </div>
                                            </div>

                                          <p>&nbsp;</p>
                                          <div class="row">
                                            <div class="col-md-6">
                                              <%= f.submit 'Save', :class => 
'btn btn-primary' %>&nbsp;&nbsp;<%= link_to "Cancel", :back, :class => 'btn btn-info' %>

查看以显示图像:

....
<div data-role="navbar">
      <ul>
        <li ><%= link_to "Offers", profile_path(@profile = current_user.profile), :data => {:icon=>"star"} 
         %></li>
        <li><a href="/tags" data-icon="tag">Tags</a></li>
        <li><%= link_to(edit_profile_path(@profile = current_user.profile)) do %>
        <%= image_tag current_user.profile.logo_image.url, :class => "img-circle" %><br>
        <%= "Account" %>
        <% end %>
        </li>
      </ul>
    </div>

这是图像更新的日志文件。正如您所见,AWS&amp; Paperclip似乎正在做他们应该做的事情来删除旧图像和保存新图像。一切似乎都运转良好:

#log file

....
Started PATCH "/profiles/1" for 127.0.0.1 at 2014-11-09 17:59:11 -0800
Processing by ProfilesController#update as HTML
Parameters: {"utf8"=>"✓",  
"authenticity_token"=>"XJiJcWbhLmeu0eJD1nvVPIDhQGRE4KhdJUlPnpY8HOo=",    "profile"=>   
{"firstname"=>"Jen", "lastname"=>"", "company"=>"", "website"=>"", "city"=>"", "state"=>"", 
"phone"=>"", "address"=>", , , ", "latitude"=>"", "longitude"=>"", "logo_image"=>#
<ActionDispatch::Http::UploadedFile:0x511bfc0 @tempfile=#<File:C:/Users/Tom/AppData/Local
/Temp/RackMultipart20141109-12208-1wc9lj4>, @original_filename="PresidioPizza_405.jpg", 
@content_type="image/jpeg", @headers="Content-Disposition: form-data; 
name=\"profile[logo_image]\"; filename=\"PresidioPizza_405.jpg\"\r\nContent-Type: image/jpeg\r
\n">}, "commit"=>"Save", "id"=>"1"}
[1m[35mProfile Load (1.0ms)[0m  SELECT  "profiles".* FROM "profiles"  WHERE 
"profiles"."id" = $1 LIMIT 1  [["id", 1]]
[1m[36m (0.0ms)[0m  [1mBEGIN[0m
[AWS S3 200 0.505819 0 retries] 
head_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/original
/selfie.jpg")  

[AWS S3 200 0.124335 0 retries] 
head_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/medium
/selfie.jpg")  

[AWS S3 200 0.118807 0 retries] 
head_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/small
/selfie.jpg")  

[AWS S3 200 0.109592 0 retries] 
head_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/thumb   
/selfie.jpg")  

Command :: file -b --mime "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-1nguzb2.jpg"
Command :: identify -format '%wx%h,%[exif:orientation]' "C:/Users/Tom/AppData/Local  
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]" 2>NUL
Command :: identify -format %m "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]"
Command :: convert "C:/Users/Tom/AppData/Local 
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]" -auto-orient -resize  
"250x250>" "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-14j5z1t"
Command :: file -b --mime "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-14j5z1t"
Command :: identify -format '%wx%h,%[exif:orientation]' "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]" 2>NUL
Command :: identify -format %m "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]"
Command :: convert "C:/Users/Tom/AppData/Local 
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]" -auto-orient -resize 
"175x175>" "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-1rsywau"
Command :: file -b --mime "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-1rsywau"
Command :: identify -format '%wx%h,%[exif:orientation]' "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]" 2>NUL
Command :: identify -format %m "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]"
Command :: convert "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk20.jpg[0]" -auto-orient -resize    
"100x100>" "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-16e15ym"
Command :: file -b --mime "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-16e15ym"
Command :: file -b --mime "C:/Users/Tom/AppData/Local
/Temp/682835cfecae2078ad6fa4af85a84f1420141109-12208-1tjtjm4.jpg"


[1m[35mSQL (1.0ms)[0m  UPDATE "profiles" SET "logo_image_file_name" = $1, 
"logo_image_file_size" = $2, "logo_image_updated_at" = $3 WHERE "profiles"."id" = 1  
[["logo_image_file_name", "PresidioPizza_405.jpg"], ["logo_image_file_size", 34800], 
["logo_image_updated_at", "2014-11-10 01:59:12.534650"]]
[paperclip] deleting /profiles/logo_images/000/000/001/original/selfie.jpg
[AWS S3 204 0.113216 0 retries] 
delete_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/original
/selfie.jpg")  

[paperclip] deleting /profiles/logo_images/000/000/001/medium/selfie.jpg
[AWS S3 204 0.113074 0 retries] 
delete_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/medium
/selfie.jpg")  

[paperclip] deleting /profiles/logo_images/000/000/001/small/selfie.jpg
[AWS S3 204 0.108656 0 retries] 
delete_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/small
/selfie.jpg")  

[paperclip] deleting /profiles/logo_images/000/000/001/thumb/selfie.jpg
[AWS S3 204 0.106705 0 retries] 
delete_object(:bucket_name=>"phototagapp",:key=>"profiles/logo_images/000/000/001/thumb
/selfie.jpg")  

[paperclip] saving /profiles/logo_images/000/000/001/original/PresidioPizza_405.jpg
[AWS S3 200 0.335884 0 retries] 

put_object(:acl=>:public_read,:bucket_name=>"phototagapp",:content_length=>34800,
:content_type=>"image/jpeg",:data=>Paperclip::UploadedFileAdapter:   
PresidioPizza_405.jpg,:key=>"profiles/logo_images/000/000/001/original/PresidioPizza_405.jpg")  

[paperclip] saving /profiles/logo_images/000/000/001/medium/PresidioPizza_405.jpg
[AWS S3 200 0.140086 0 retries] 
put_object(:acl=>:public_read,:bucket_name=>"phototagapp",:content_length=>19933,
:content_type=>"image/jpeg",:data=>Paperclip::FileAdapter: 
682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-14j5z1t,
:key=>"profiles/logo_images/000/000/001/medium/PresidioPizza_405.jpg")  

[paperclip] saving /profiles/logo_images/000/000/001/small/PresidioPizza_405.jpg
[AWS S3 200 0.142438 0 retries] 
put_object(:acl=>:public_read,:bucket_name=>"phototagapp",:content_length=>11679,
:content_type=>"image/jpeg",:data=>Paperclip::FileAdapter: 
682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-1rsywau,
:key=>"profiles/logo_images/000/000/001/small/PresidioPizza_405.jpg")  

[paperclip] saving /profiles/logo_images/000/000/001/thumb/PresidioPizza_405.jpg
[AWS S3 200 0.222046 0 retries] 
put_object(:acl=>:public_read,:bucket_name=>"phototagapp",:content_length=>5067,
:content_type=>"image/jpeg",:data=>Paperclip::FileAdapter: 
682835cfecae2078ad6fa4af85a84f1420141109-12208-192uk2020141109-12208-16e15ym,
:key=>"profiles/logo_images/000/000/001/thumb/PresidioPizza_405.jpg")  

[1m[36m (2.0ms)[0m  [1mCOMMIT[0m
Redirected to http://localhost:3000/profiles/1
Completed 302 Found in 3560ms (ActiveRecord: 4.0ms)


Started GET "/profiles/1" for 127.0.0.1 at 2014-11-09 17:59:14 -0800
Processing by ProfilesController#show as HTML
Parameters: {"id"=>"1"}
[1m[35mProfile Load (1.0ms)[0m  SELECT  "profiles".* FROM "profiles"  WHERE  
"profiles"."id" = $1 LIMIT 1  [["id", 1]]
[1m[36mProfile Load (1.0ms)[0m  [1mSELECT "profiles".* FROM "profiles"[0m
[1m[35mOffer Load (1.0ms)[0m  SELECT "offers".* FROM "offers"  WHERE 
"offers"."offer_status" = 'On'
Rendered profiles/show.html.erb within layouts/application (2.0ms)
[1m[36mUser Load (1.0ms)[0m  [1mSELECT  "users".* FROM "users"  WHERE "users"."id" = 1  
ORDER BY "users"."id" ASC LIMIT 1[0m
[1m[35mProfile Load (0.0ms)[0m  SELECT  "profiles".* FROM "profiles"  WHERE 
"profiles"."user_id" = $1 LIMIT 1  [["user_id", 1]]
Completed 200 OK in 447ms (Views: 438.6ms | ActiveRecord: 4.0ms)

以下是视图显示的内容:

<img alt="Presidiopizza 405" class="img-circle" src="http://phototagapp.s3.amazonaws.com 
/profiles/logo_images/000/000/001/original/PresidioPizza_405.jpg%3F1415584752" />

问题似乎是%3F1415584752被附加到文件名。我已经测试了AWS S3没有Paperclip,而是使用S3_Direct_Post和图像正确显示,没有奇怪的扩展并使用相同的AWS S3设置/凭证。但是,我想使用回形针。希望有人能指出我的解决方案。我猜它可能是愚蠢的。

当我访问AWS S3管理控制台时,图像正确保存在正确的文件夹结构和文件名中。

这是CORS设置。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>http://localhost:3000</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

谢谢

2 个答案:

答案 0 :(得分:0)

试试这个

 has_attached_file :image,
      :logo_image, 
      :styles => { :medium => "250x250>", :small => "175x175>", :thumb => "100x100>" } 
      :storage => :s3,
       ## example credentials path
      :s3_credentials => Rails.root.join('config/amazon_s3.yml').to_s,
      :s3_protocol => 'https',
      :path => "logo/:basename.:extension"

答案 1 :(得分:0)

我相信我通过执行以下操作解决了这个问题:

paperclip.rb初始化程序:

Paperclip::Attachment.default_options.merge!(
  ...
  use_timestamp: false,
  ...)

点击此处了解更多信息: https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/attachment.rb