使用Rails和回形针上传

这是“使用Rails上传”系列中的最后一篇文章。 在过去的几个月中,我们已经讨论了神殿,蜻蜓和载波波的宝石。 今天的客人是Thoughtbot的Paperclip ,该公司管理着诸如FactoryGirl和Bourbon之类的宝石。

Paperclip可能是Rails最受欢迎的附件管理解决方案(下载量超过1300万),并且有一个很好的理由:它具有许多功能,强大的社区和详尽的文档。 因此,希望您渴望了解有关此宝石的更多信息!

在本文中,您将学习如何:

  • 准备回形针安装
  • 将Paperclip集成到Rails应用程序中
  • 添加附件验证
  • 生成缩略图并处理图像
  • 混淆URL
  • 在Amazon S3上存储附件
  • 通过引入授权逻辑来保护云中的文件

GitHub上提供了本文的源代码。

准备工作

在深入研究代码之前,让我们首先讨论一些要成功使用Paperclip时需要了解的警告

  • Paperclip的最新版本支持Rails 4.2+和Ruby 2.1+。 该宝石也可以在没有Rails的情况下使用。
  • ImageMagick必须安装在您的PC上(所有主要平台都可用),并且Paperclip应该能够访问它。
  • file命令应该可以从命令行使用。 对于Windows,可通过开发工具包获得,因此,如果尚未安装DevKit,请按照以下说明进行操作

准备就绪后,继续创建没有默认测试套件的新Rails应用程序(我将使用Rails 5.0.2):

rails new UploadingWithPaperclip -T

集成回形针

放入回形针宝石:

宝石文件
gem "paperclip", "~> 5.1"

安装它:

bundle install

假设我们正在创建一个展示书单的书架应用程序。 每本书都有标题,描述,作者姓名和封面图像。 首先,请生成并应用以下迁移:

rails g model Book title:string description:text image:attachment author:string
rails db:migrate

请注意Paperclip为我们提供的attachment类型。 在幕后,它将为我们创建四个字段:

  • image_file_name
  • image_file_size
  • image_content_type
  • image_updated_at

与Shrine和Carrierwave宝石相反,Paperclip没有单独的配置文件。 所有设置都是使用has_attached_file方法在模型内部定义的,因此请立即添加:

型号/book.rb
has_attached_file :image

在继续学习主要部分之前,我们还创建一个控制器以及一些视图和路线。

创建控制器,视图和路径

我们的控制器将是非常基本的:

books_controller.rb
class BooksController < ApplicationController
  before_action :set_book, only: [:show, :download]

  def index
    @books = Book.order('created_at DESC')
  end

  def new
    @book = Book.new
  end

  def show
  end

  def create
    @book = Book.new(book_params)
    if @book.save
      redirect_to books_path
    else
      render :new
    end
  end

  private

  def book_params
    params.require(:book).permit(:title, :description, :image, :author)
  end

  def set_book
    @book = Book.find(params[:id])
  end
end

这是索引视图和局部视图:

views / books / index.html.erb
<h1>Bookshelf</h1>

<%= link_to 'Add book', new_book_path %>
<ul>
  <%= render @books %>
</ul>
views / books / _book.html.erb
<li>
  <strong><%= link_to book.title, book_path(book) %></strong> by <%= book.author %>
</li>

现在的路线:

config / routes.rb
Rails.application.routes.draw do
  resources :books
  root to: 'books#index'
end

真好! 现在,让我们继续到主要部分,并编写动作和表单的代码。

上载档案

总而言之,使用Paperclip进行上传很容易。 您只需要允许相应的属性(在我们的例子中是image属性,并且我们已经允许了它)并在您的表单中显示文件字段。 让我们现在就开始做吧:

views / books / new.html.erb
<h1>Add book</h1>

<%= render 'form', book: @book %>
views / books / _form.html.erb
<%= form_for book do |f| %>
  <div>
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>

  <div>
    <%= f.label :author %>
    <%= f.text_field :author %>
  </div>

  <div>
    <%= f.label :description %>
    <%= f.text_area :description %>
  </div>

  <div>
    <%= f.label :image %>
    <%= f.file_field :image %>
  </div>

  <%= f.submit %>
<% end %>

使用此设置,您已经可以开始执行上传了,但是最好引入一些验证。

添加验证

验证在回形针可以使用旧助手等书面validates_attachment_presencevalidates_attachment_content_type或通过采用validates_attachment方法一次定义多个规则。 让我们坚持使用后一种选择:

型号/book.rb
validates_attachment :image,
                       content_type: { content_type: /\Aimage\/.*\z/ },
                       size: { less_than: 1.megabyte }

如您所见,该代码非常简单。 我们要求文件的图像大小小于1兆字节。 请注意,如果验证失败,将不执行任何后处理。 回形针已经为英语设置了一些错误消息,但是如果您想支持其他语言,请将回形针i18n gem包含在Gemfile中

值得一提的另一件事是,回形针要求您验证所有附件的内容类型或文件名,否则将引发错误。 如果您100%确定不需要此类验证(这种情况很少见),请使用do_not_validate_attachment_file_type明确指出不应检查的字段。

添加验证后,我们还以表单形式显示错误消息:

views / shared / _errors.html.erb
<% if object.errors.any? %>
  <h3>Some errors were found:</h3>
  <ul>
    <% object.errors.full_messages.each do |message| %>
      <li><%= message %></li>
    <% end %>
  </ul>
<% end %>
views / books / _form.html.erb
<%= render 'shared/errors', object: book %>

显示影像

好的,现在应该以某种方式显示上传的图像。 这是通过使用image_tag帮助器和url方法完成的。 创建一个显示视图:

views / books / show.html.erb
<h1><%= @book.title %> by <%= @book.author %></h1>

<%= image_tag(@book.image.url) if @book.image.exists? %>

<p><%= @book.description %></p>

仅当驱动器上确实存在图像时,我们才显示 。 此外,如果您使用的是云存储,那么Paperclip将执行网络请求并检查文件的存在。 当然,此操作可能需要一些时间,因此您可以使用present?file? 方法:它们只是确保image_file_name字段填充了某些内容。

URI混淆

默认情况下,所有附件都存储在public / system文件夹中,因此您可能希望将其从版本控制系统中排除:

.gitignore
public/system

但是,显示文件的完整URI并非总是一个好主意,并且您可能需要以某种方式对其进行混淆。 启用混淆的最简单方法是为has_attached_file method提供两个参数:

型号/book.rb
url: "/system/:hash.:extension",
hash_secret: "longSecretString"

适当的值将自动插入到urlhash_secret是必填字段,生成它的最简单方法是使用:

rails secret

处理样式

在许多情况下,最好以预定的宽度和高度显示图像的缩略图,以节省带宽。 回形针通过使用样式来解决此问题:每个样式都有一个名称和一组规则,例如尺寸,格式,质量等。

假设我们希望将原始图像及其缩略图转换为JPEG格式。 缩略图应裁剪为300x300px:

型号/book.rb
has_attached_file :image,
                    styles: {
                        thumb: ["300x300#", :jpeg],
                        original: [:jpeg]
                    }

#是几何设置,其含义是:“如果需要,请在保持宽高比的同时进行裁剪。”

我们还可以为每种样式提供其他转换选项。 例如,让我们为拇指提供70%的质量,同时删除所有元数据,为原始图像提供90%的质量以使其更小:

型号/book.rb
has_attached_file :image,
                    styles: {
                        thumb: ["300x300#", :jpeg],
                        original: [:jpeg]
                    },
                    convert_options: {
                        thumb: "-quality 70 -strip",
                        original: "-quality 90"
                    }

真好! 显示缩略图并提供原始图像的链接:

views / books / show.html.erb
<%= link_to(image_tag(@book.image.url(:thumb)), @book.image.url, target: '_blank') if @book.image.exists? %>

请注意,例如,与Carrierwave不同,Paperclip不允许您编写@book.image.thumb.url

如果由于某种原因希望手动更新上传的图像,则可以使用以下命令仅刷新缩略图,添加缺少的样式或刷新所有图像:

  • rake paperclip:refresh:thumbnails CLASS=Book
  • rake paperclip:refresh:missing_styles CLASS=Book
  • rake paperclip:refresh CLASS=Book

在云中存储文件

像所有类似的解决方案一样,Paperclip 允许您将文件上传到云中。 开箱即用,它支持S3和Fog适配器,但是Azure和Dropbox都有第三方gem。 在本部分中,我将向您展示如何将Paperclip与Amazon S3集成。 首先,放入aws-sdk gem:

gem 'aws-sdk'

安装它:

bundle install

接下来,为has_attached_file方法提供一组新的选项:

型号/book.rb
has_attached_file :image,
                    styles: {
                        thumb: ["300x300#", :jpeg],
                        original: [:jpeg]
                    },
                    convert_options: {
                        thumb: "-quality 70 -strip",
                        original: "-quality 90"
                    },
                    storage: :s3,
                    s3_credentials: {
                        access_key_id: ENV["S3_KEY"],
                        secret_access_key: ENV["S3_SECRET"],
                        bucket: ENV["S3_BUCKET"]
                    },
                    s3_region: ENV["S3_REGION"]

在这里,我坚持使用dotenv-rails gem来设置环境变量。 您可以直接在模型内部提供所有值,但不要使其公开可用。

有趣的是s3_credentials还接受包含密钥和存储桶名称的YAML文件的路径。 此外,您可以为不同的环境设置不同的值,如下所示:

development:
  access_key_id: key1
  secret_access_key: secret1
production:
  access_key_id: key2
  secret_access_key: secret2

而已! 现在,您上传的所有文件都将位于S3存储桶中。

保护云中的文件

假设您不希望所有人都可以使用自己上传的文件。 默认情况下,所有上传到云中的文件都标记为公开,这意味着任何人都可以通过直接链接打开文件。 如果您希望引入一些授权逻辑并检查谁可以查看该文件,则将s3_permissions选项设置为:private如下所示:

has_attached_file :image,
                    styles: {
                        thumb: ["300x300#", :jpeg],
                        original: [:jpeg]
                    },
                    convert_options: {
                        thumb: "-quality 70 -strip",
                        original: "-quality 90"
                    },
                    storage: :s3,
                    s3_credentials: {
                        access_key_id: ENV["S3_KEY"],
                        secret_access_key: ENV["S3_SECRET"],
                        bucket: ENV["S3_BUCKET"]
                    },
                    s3_region: ENV["S3_REGION"],
                    s3_permissions: :private

但是,现在,除了您之外,没有人可以看到这些文件。 因此,让我们为BooksController创建一个新的download操作:

books_controller.rb
def download
    redirect_to @book.image.expiring_url
  end

此操作将仅通过过期链接将用户重定向到该图像。 使用这种方法,您现在可以使用CanCanCanPundit之类的gem引入任何授权逻辑。

不要忘记设置会员路线:

config / routes.rb
resources :books do
    member do
      get 'download'
    end
  end

该帮助程序应该这样使用:

link_to('View image', download_book_path(@book), target: '_blank')

结论

我们到了本文的结尾! 今天,我们已经看到了用于Rails的附件管理解决方案Paperclip,并讨论了其主要概念。 该gem还有更多内容,因此请务必查看其文档

此外,我建议访问Paperclip的Wiki页面,因为它提供了“操作方法”列表的列表以及指向支持Azure和Cloudinary的第三方gem的大量链接,并允许您轻松地缩小上传的文件。

感谢您与我在一起,很快再见!

翻译自: https://code.tutsplus.com/articles/uploading-with-rails-and-paperclip--cms-28412

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值