【问题标题】:Getting Paperclip to upload to S3 in development and production在开发和生产中让 Paperclip 上传到 S3
【发布时间】:2017-08-17 10:35:11
【问题描述】:

我一直在尝试让 Paperclip 将图像上传到 Amazon S3 时遇到困难。虽然我一开始让程序正常工作,但它只会在本地保存(尽管存储方法设置为 s3),一旦我发现我需要覆盖默认路径,它就会因写入错误而崩溃。

我不知道它是否重要,但我正在使用 Devise 并将 profile_image 添加到用户模型中。

我正在尝试从 Heroku 关注 this guide

这是第一个仅在本地写入的设置,尽管似乎是为 S3 设置的:

user.rb
    class User < ApplicationRecord
      has_attached_file :profile_image, styles: {
        thumb: '100x100>',
        square: '200x200#',
        medium: '300x300>'
      }
      validates_attachment_content_type :profile_image, :content_type => /\Aimage\/.*\Z/
end

production.rb 和 development.rb

config.paperlip_defaults = {
    storage: :s3,
    s3_credientials: {
      bucket: ENV.fetch('S3_BUCKET_NAME'),
      access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
      secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
      s3_region: ENV.fetch('AWS_REGION')
    }
  }
  Paperclip.options[:command_path] = '/usr/local/bin/'

上传表单的一部分 app/views/devise/registrations/edit.html.erb

    <div class="form-group">
      <% if @user.profile_image.present? %>
        <%= image_tag(current_user.profile_image.url(:square)) %><br />
        <%= link_to 'Remove profile image', remove_profile_image_path, method: :put, data: { confirm: 'Are you sure?' }, type: 'button' %> 
      <% else %>
        <%= f.label :profile_image %>
        <%= f.file_field :profile_image %>
      <% end %>
    </div>

使用此设置,Paperclip 可以工作,但它只会在本地保存图像(这在开发和部署在 Heroku 上都是如此)。

接下来,我尝试强制显示 URL 来自 AWS,方法是将其添加到

config/initializers/paperclip.rb

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

这确实会强制图像路径来自那里(当我为已经附加图像的用户刷新页面时,由于没有上传图像而损坏)。但是,在我删除了这张图片后,我无法再上传了。每次我尝试上传时都会收到此错误:

Errno::EACCES in Devise::RegistrationsController#update

Permission denied @ dir_s_mkdir - /users/profile_images

为了解决这个问题,我添加了一个额外的初始化程序(来自 Heroku 教程)

Paperclip::Attachment.default_options[:s3_host_name] = 's3-us-east-1.amazonaws.com'

这不起作用,我尝试在 production.rb 和 development.rb 中添加一行但没有成功(我尝试同时添加到默认哈希和凭据哈希)

s3_domain_url: 's3-us-east-1.amazonaws.com'

我了解该错误是本地写入错误,但我的具体问题(除了如何做到这一点):

为什么 Paperclip 会忽略默认值中的存储值并在本地保存(在第一种情况下)? 为什么它试图写入我的本地磁盘(在第二种情况下)而不是上传到 S3?

更新 宝石文件

source 'https://rubygems.org'

ruby '2.3.3'

gem 'rails',                   '~> 5.0.0', '>= 5.0.0.1'
gem 'puma',                    '~> 3.0'
gem 'sass-rails',              '~> 5.0'
gem 'uglifier',                '>= 1.3.0'
gem 'coffee-rails',            '~> 4.2'
gem 'jquery-rails'
gem 'turbolinks',              '~> 5'
gem 'jbuilder',                '~> 2.5'
gem 'bcrypt',                  '~> 3.1.7'
gem 'devise'
gem 'font-awesome-rails'
gem 'bourbon',                 '5.0.0.beta.7'
gem 'neat',                    '2.0.0'
gem 'autoprefixer-rails'
gem 'font-awesome-sass',       '~> 4.7.0'
gem 'paperclip'
gem 'aws-sdk',                 '~> 2.3'

group :development, :test do
  gem 'sqlite3'
  gem 'byebug', platform: :mri
  gem 'dotenv-rails'
end

group :development do
  gem 'listen', '~> 3.0.5'
  gem 'web-console'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
  gem 'rubocop', require: false
  gem 'haml-lint', require: false
end

group :test do
  gem 'guard', '2.13.0'
  gem 'minitest-reporters', '1.1.9'
  gem 'coveralls', require: false
  gem 'capybara'
  gem 'factory_girl_rails', '~>4.0'
end

group :production do
  gem 'pg', '0.18.4'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

【问题讨论】:

    标签: ruby-on-rails heroku amazon-s3 devise paperclip


    【解决方案1】:

    问题中的设置方式和所使用的文档对于 Heroku 上的 Paperclip ~&gt; 5.1AWS-SDK ~&gt; 2.0 要么错误要么不再有效。

    还有第二个未说明的问题,一旦在开发中工作就会变得明显,开发上传将覆盖生产上传,反之亦然。

    这是使用上传到 S3 的开发环境和生产环境的设置。

    1. 将初始化程序缩减为仅共享信息

    config/initializers/paperclip.rb

    Paperclip::Attachment.default_options[:path] = ':class/:attachment/:id_partition/:style/:filename'
    Paperclip::Attachment.default_options[:storage] = :s3
    Paperclip::Attachment.default_options[:s3_protocol] = 'https'
    
    1. 在用户模型中定义有效的图像和图像大小

    app/model/users.rb

    has_attached_file :profile_image, styles: {
        thumb: '100x100>',
        square: '200x200#',
        medium: '300x300>'
      }
    validates_attachment_content_type :profile_image, :content_type => /\Aimage\/.*\Z/
    
    1. 注册第二个开发映像存储桶并将必要的变量添加到 .ENV 文件中

    .ENV

    # Shared S3 variables
    AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXX
    AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXX
    
    # Development variables
    DEV_S3_BUCKET_NAME=your-dev-bucket-name
    
    # Production variables
    S3_BUCKET_NAME=your-production-bucket-name
    
    1. 将默认选项和命令路径放在各自的环境文件中

    config/environments/development.rb

    Paperclip::Attachment.default_options[:s3_credentials] = {
        :bucket => ENV['DEV_S3_BUCKET_NAME'],
        :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
        :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
        :region => 'us-east-2'
      }
    Paperclip::Attachment.default_options[:s3_region] = 'us-east-2'
    Paperclip::Attachment.default_options[:s3_host_name] = 's3.us-east-2.amazonaws.com'
    Paperclip.options[:command_path] = 'usr/local/bin'
    

    在我的例子中,我对区域和主机名进行了硬编码,您可以根据需要提取它们。我还选择将开发图像托管在不同的区域,只是为了多一点分离。另请注意,我创建的第一个存储桶(生产)不会将该区域附加到地址。我不确定为什么 S3 是这样配置的,但是您可以通过上传图像然后在 AWS 控制台中的文件夹中向下钻取直到找到图像 URL 来检查您的特定图像路径。

    config/environments/production.rb

    Paperclip::Attachment.default_options[:s3_credentials] = {
        :bucket => ENV['S3_BUCKET_NAME'],
        :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
        :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
        :region => 'us-east-1'
      }
    Paperclip::Attachment.default_options[:s3_region] = 'us-east-1'
    Paperclip::Attachment.default_options[:s3_host_name] = 's3.amazonaws.com'
    Paperclip.options[:command_path] = 'usr/local/bin'
    

    【讨论】:

      【解决方案2】:

      您可能需要更改路径选项

      PaperClip::Attachment.default_options[:path] = ":rails_root/public/system/.../the/rest/of/the/desired/path"
      

      【讨论】:

      • 这确实解决了写入错误,但是图片仍然保存在本地,没有上传到S3
      • 你能发布你的 Gemfile 吗?
      • 底部添加
      猜你喜欢
      • 2011-12-29
      • 2019-11-24
      • 2018-07-19
      • 2012-02-22
      • 1970-01-01
      • 2016-05-08
      • 2014-01-18
      • 1970-01-01
      • 2017-09-03
      相关资源
      最近更新 更多