Rails 4 + Paperclip + Amazon S3:图片作为原件上传,但 none 样式(拇指和中号)

Rails 4 + Paperclip + Amazon S3: images are uploaded as originals, but none in styles (thumb & medium sizes)

我正在创建一个 Rails 应用程序,它有两个资源,收集器和项目,并且都需要通过 Paperclip 将图像上传到 Amazon s3 作为存储。

我为收藏家设置了头像,效果很好,这意味着 s3 setup/config 部分应该没问题。但是,当我使用完全相同的代码为项目设置图像时,只有原始图像会上传到 s3。我去我的 s3 控制台检查文件:虽然创建了缩略图和中型文件夹,但它们都是空的。

注意:阅读 更新 II 部分以获取新代码。仍然有同样的问题。

这是我的项目模型中的代码:

class Item < ActiveRecord::Base
  belongs_to :collector

  has_attached_file :item_img,
    :styles => { :thumb => '320x320>', :medium => '640x640>'},
    :storage => :s3,
    :url => ':s3_domain_url',
    :path => '/:class/:attachment/:id_partition/:style/:filename',
    :bucket => "my-project-name",
    :s3_credentials => S3_CREDENTIALS

  has_attached_file :item_img
  # Validate the attached image is image/jpg, image/png, etc
  validates_attachment_content_type :item_img, :content_type => /\Aimage\/.*\Z/
  validates_attachment_file_name :item_img, :matches => [/png\Z/, /jpe?g\Z/]
  validates_with AttachmentSizeValidator, :attributes => :item_img, :less_than => 1.megabytes

end

这是我的 Collector 模型中的代码(工作得很好):

class Collector < ActiveRecord::Base
  has_many :items, dependent: :destroy

  # This method associates the attribute ":avatar" with a file attachment
  has_attached_file :avatar,
    :styles => { :thumb => '50x50>', :medium => '200x200>'},
    :default_url => ":style/missing.jpg",
    :storage => :s3,
    :url => ':s3_domain_url',
    :path => '/:class/:attachment/:id_partition/:style/:filename',
    :bucket => "my-project-name",
    :s3_credentials => S3_CREDENTIALS

  # Validate the attached image is image/jpg, image/png, etc
  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
  validates_attachment_file_name :avatar, :matches => [/png\Z/, /jpe?g\Z/]
  validates_with AttachmentSizeValidator, :attributes => :avatar, :less_than => 1.megabytes

  validates :email, email_format: { message: "This doesn't look like an email address. Please try again."}
end

什么可能导致问题?如果您需要来自其他文件的更多代码,请告诉我。

更新一: 我得到的错误是 403 Access Forbidden,考虑到这些文件无论如何都没有根据样式上传到 s3 控制台,这有点令人惊讶。

更新二: 在我 post 编辑了这个问题并阅读了很多关于回形针 + s3 问题的 post 之后,我仍然没有找到任何解决方案。所以我决定在 s3 上重新创建用于开发和生产的新存储桶。在浏览与回形针和 s3 相关的所有代码时,我沿途改进了我的代码,因此代码发生了很大变化。

首先,这是我的 Gemfile:

source 'https://rubygems.org'

ruby '2.1.2'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.6'
# Use postgresql as the database for Active Record
gem 'pg'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer',  platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'

gem 'jquery-ui-rails'

# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0',          group: :doc

# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring',        group: :development

# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'

gem 'httparty'
gem 'actionview', '~> 4.1.5', require: "action_view"

gem 'activesupport', '~> 4.1.6'

gem 'paperclip'
gem 'aws-sdk'

gem 'newrelic_rpm'

gem 'validates_email_format_of'


group :development, :test do
  gem 'rspec-rails', '~> 3.0.0'
  gem 'pry'
  gem 'pry-rails'
  gem 'shotgun'
  gem 'annotate'
  gem 'capybara'
  gem 'cucumber-rails', :require => false
  gem 'launchy', '~> 2.4.2'
end

group :test do
  gem 'shoulda-matchers', require: false
end

group :production do
  gem 'rails_12factor'
  gem 'rails_serve_static_assets'
end

我在 config/initializers 中有一个 s3.rb 文件:

S3_CREDENTIALS = {
  :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
  :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
  :bucket => ENV['S3_BUCKET_NAME']
}

为了访问 S3_CREDENTIALS,为了开发,我将所有信息保存在我的 .bash_profile 中,如下所示:

export S3_BUCKET_NAME=“my-project-name_dev”
export AWS_ACCESS_KEY_ID=“asdfasdfasdfasdf”
export AWS_SECRET_ACCESS_KEY=“ASDFASDFASDFASDFASDFASDFASDF”

为了生产,我在 Heroku 中将上述三个凭据保存为 "Config Variables"。

对于config/initializers/paperclib.rb,我有以下代码:

Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'

Paperclip::Attachment.default_options[:s3_host_name] = 's3.amazonaws.com'

关于模型,我缩短了之前版本的路径,并且还更改了:bucket,使其适用于开发和生产:

class Collector < ActiveRecord::Base
  has_many :items, dependent: :destroy

  has_attached_file :avatar,
    :styles => { :thumb => '50x50>', :medium => '200x200>'},
    :default_url => ":style/missing.jpg",
    :url => ':s3_domain_url',
    :path => '/:class/:style/:filename',
    :storage => :s3,
    :bucket => ENV['S3_BUCKET_NAME'],
    :s3_credentials => S3_CREDENTIALS

  validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
  validates_attachment_file_name :avatar, :matches => [/png\Z/, /jpe?g\Z/]
  validates_with AttachmentSizeValidator, :attributes => :avatar, :less_than => 1.megabytes

  validates :email, email_format: { message: "This doesn't look like an email address. Please try again."}
end

上面的 Collector 模型代码在生产中工作得很好,虽然它说它 missing :bucket option 在开发中,这是一个奇怪的问题,但不是我对这个 post 的主要关注。我仍然对项目有同样的问题:

class Item < ActiveRecord::Base
  belongs_to :collector

  has_attached_file :item_img,
    :styles => { :small => '320x320>', :large => '640x640>' },
    :url => ':s3_domain_url',
    :path => '/:class/:style/:filename',
    :storage => :s3,
    :bucket => ENV['S3_BUCKET_NAME'],
    :s3_credentials => S3_CREDENTIALS

  has_attached_file :item_img
  # Validate the attached image is image/jpg, image/png, etc
  validates_attachment_content_type :item_img, :content_type => /\Aimage\/.*\Z/
  validates_attachment_file_name :item_img, :matches => [/png\Z/, /jpe?g\Z/]
  validates_with AttachmentSizeValidator, :attributes => :item_img, :less_than => 1.megabytes

end

最奇怪的是,即使在创建了一个全新的存储桶之后,保存为 "original" 图像的图像仍然采用旧的 :path,如我的旧代码中所定义::path => '/:class/:attachment/:id_partition/:style/:filename',而不是我新定义它的方式::path => '/:class/:style/:filename'。也许是因为上面 paperclip.rb 中的回形针默认值,但我认为它会覆盖默认值,就像 Collector 模型一样。尽管如此,同样的老问题仍然存在:所有样式都丢失了,甚至文件夹也没有; "original" 文件夹中仅上传原件。

如果您需要更多信息,请告诉我。

正如我的忠实朋友@qubit 在评论部分指出的那样,我在 Item 模型中将 has_attached_file :item_img 与我的验证器分组在一起,因为我以某种方式认为这是一种不同的验证形式并忽略了它。通过删除该行,我立即解决了问题。

再次感谢@qubit!