Rails 5.2 活动存储:预览、Poppler 和解决许可陷阱
Rails 5.2 上个月刚刚发布,其中一项重要的新功能是 Active Storage。Active Storage 为 Active Record 模型提供文件上传和附件功能,并支持多种后端服务(例如 AWS S3)。虽然像Paperclip这样的库也能实现类似的功能,但这是 Rails 首次将此功能集成到其产品中。在 Heroku,我们认为云存储是一种最佳实践,因此我们确保它能在我们的平台上正常运行。在本文中,我们将分享我们如何为 Rails 5.2 的发布做好准备,以及如何立即使用全新的 Active Storage 功能部署应用程序。
信任,但要核实
在 Heroku,信任是我们最重要的价值观。当我们得知 Active Storage 将随 Rails 5.2 一起发布时,我们便开始尝试它的所有功能。Active Storage 最便捷的功能之一就是预览 PDF 和视频。它无需通过文本链接指向资源,而是从文件中提取 PDF 或视频的截图并渲染到页面上。
Rails 5.2 测试版使用了流行的开源工具 FFmpeg 和 MuPDF 来生成视频和 PDF 预览。我们通过安全和法务部门对这些新的二进制依赖项进行了审查,发现 MuPDF 采用 AGPL 许可,并且某些用途需要商业许可。如果我们只是默认将 MuPDF 添加到 Rails 5.2 及更高版本的应用程序中,许多客户将不会意识到他们需要购买 MuPDF 才能将其用于商业用途。
2017 年 9 月, AGPL 许可的限制引起了公众的关注。为了准备 5.2 版本的发布,我们的工程师Terence Lee致力于更新 Active Storage,使 PDF 预览功能也能使用开源后端,而无需商业许可。2018 年 2 月,我们向 Rails 提交了一个 PR,引入了使用 poppler PDF 作为 MuPDF 替代方案的功能。该 PR 大约一个月后被合并,现在任何 Rails 5.2 用户——无论是否使用 Heroku——都可以渲染 PDF 预览,而无需购买商业许可。
Heroku 上的 Active Storage 示例应用
如果您已经有一个实现了 Active Storage 的应用程序,您可以跳转到我们的 DevCenter 文档,了解有关 Active Storage 的更多信息。
或者,您可以使用我们的示例应用。这是一个基于 Rails 5.2 的数字公告板应用,用户可以在上面发布视频、PDF 和图片。您可以在 GitHub 上查看源代码,或者使用 Heroku 按钮部署该应用:
注意:此示例应用需要付费的 S3 插件。
这里有一个视频示例,展示了该应用程序的功能。
打开首页后,选择合适的资源,然后提交表单。视频中,文件mp4上传到 S3 后,Rails 会借助一些工具实时生成预览ffmpeg。非常简洁高效。
Heroku 上的 Active Storage
如果您使用按钮部署了示例应用程序,它已经通过 Heroku 配置运行app.json,但是如果您有自己的应用程序想要部署,您如何设置才能使其在 Heroku 上运行?
根据Active Storage 的 DevCenter 文档,您需要一个所有 dyno 都能访问的文件存储服务。示例中使用的是 Heroku 的 S3 插件Bucketeer,当然您也可以使用现有的 S3 凭据。
首先,将适用于 S3 的 AWS gem 添加到 Gemfile 中;如果您还要修改图像,请添加 Mini Magick:
gem "aws-sdk-s3", require: false
gem 'mini_magick', '~> 4.8'
$ bundle install更新 Gemfile 后别忘了这样做。
接下来,在文件amazon中添加一个选项,config/storage.yml指向 S3 配置,本例中我们使用的是 Bucketeer 设置的配置:
amazon:
service: S3
access_key_id: <%= ENV['BUCKETEER_AWS_ACCESS_KEY_ID'] %>
secret_access_key: <%= ENV['BUCKETEER_AWS_SECRET_ACCESS_KEY'] %>
region: <%= ENV['BUCKETEER_AWS_REGION'] %>
bucket: <%= ENV['BUCKETEER_BUCKET_NAME'] %>
然后确保您的应用已设置为:amazon在生产环境中使用配置存储:
config.active_storage.service = :amazon
如果您忘记执行此步骤,默认存储方式会将:local文件保存到磁盘。这种方式不适合在生产环境中处理上传的文件。如果您不小心将此部署到 Heroku,文件最初看起来似乎已上传,但如果您运行多个 dyno,它们会在随机请求中消失。dyno 重启后,文件将彻底丢失。您可以在 Heroku 开发者中心获取有关临时磁盘的更多信息。
最后,要让此功能在生产环境中正常运行,您还需要安装一个自定义构建包,该构建包会安装用于生成资源预览的二进制依赖ffmpeg项poppler:
$ heroku buildpacks:add -i 1 https://github.com/heroku/heroku-buildpack-activestorage-preview
完成后即可部署到 Heroku!
向现有应用添加活动存储
如果你的应用还没有启用 Active Storage,你可以添加它。首先,你需要运行以下命令启用 Active Storage Blob 存储:
$ bin/rails active_storage:install
这将添加一个迁移,使 Rails 能够跟踪已上传的文件。
接下来,你需要一个模型来“附加”文件。你可以使用现有模型,也可以创建一个新模型。示例应用中bulletin使用的是一个几乎为空的模型:
$ bin/rails generate scaffold bulletin
接下来,对应用程序运行迁移:
$ bin/rails db:migrate
数据库迁移完成后,更新模型,让 Rails 知道你打算能够向其中附加文件:
class Bulletin < ApplicationRecord
has_one_attached :attachment
end
完成上述步骤后,我们还需要三个部分:一个用于上传附件的表单、一个用于保存附件的控制器,以及一个用于渲染附件的视图。
如果您已有表单,可以通过file_field视图助手添加附件字段,如下所示:
<%= form.file_field :attachment %>
您可以在示例应用中看到带有附件的表单示例。创建表单后,您需要保存附件。
在这个示例应用中,首页包含表单和视图。在公告控制器中,附件会被保存,然后将用户重定向回主公告列表:
def create
@bulletin = Bulletin.new()
@bulletin.attachment.attach(params[:bulletin][:attachment])
@bulletin.save!
redirect_back(fallback_location: root_path)
end
最后,在欢迎视图中,我们遍历每一项公告,并根据附件的类型,以不同的方式呈现它。
在 Active Storage 中,previewable?如果系统安装了正确的二进制文件,该方法将对 PDF 和视频返回 true。variable?如果安装了相应的二进制文件,该方法也将对图像返回 true mini_magick。如果以上两种情况都不成立,则附件很可能是下载后才能查看的文件。以下是该逻辑的表示方式:
<ul class="no-bullet">
<% @bulletin_list.each do |bulletin| %>
<li>
<% if bulletin.attachment.previewable? %>
<%= link_to(image_tag(bulletin.attachment.preview(resize: "200x200>")), rails_blob_path(bulletin.attachment, disposition: "attachment"))
%>
<% elsif bulletin.attachment.variable? %>
<%= link_to(image_tag(bulletin.attachment.variant(resize: "200x200")), rails_blob_path(bulletin.attachment, disposition: "attachment"))%>
<% else %>
<%= link_to "Download file", rails_blob_path(bulletin.attachment, disposition: "attachment") %>
<% end %>
</li>
<% end %>
</ul>
一旦你的应用程序具备了所有这些功能,并且配置了 Active Storage 使其在生产环境中运行,你的用户就可以轻松地上传和下载文件了。
文章来源:https://dev.to/heroku/rails-52-active-storage-previews-poppler-and-solving-licensing-pitfalls-2b80
