Active Storage¶ ↑
Active Storage 可以轻松地将文件上传到云服务(例如 Amazon S3 或 Google Cloud Storage)并将其关联到 Active Records。它支持主服务和镜像服务以提高冗余度。它还为测试或本地部署提供了一个磁盘服务,但主要侧重于云存储。
文件可以直接从服务器上传到云端,也可以直接从客户端上传到云端。
图像文件还可以使用按需变体进行转换,以实现质量、宽高比、大小或任何其他 MiniMagick 或 Vips 支持的转换。
您可以在 Active Storage 概述 指南中了解更多关于 Active Storage 的信息。
与其他存储解决方案的比较¶ ↑
Active Storage 与 Rails 中其他附件解决方案的关键区别在于使用了内置的 Blob 和 Attachment 模型(由 Active Record 支持)。这意味着现有的应用程序模型不需要修改以添加额外的列来关联文件。Active Storage 通过 Attachment 连接模型使用多态关联,该模型又连接到实际的 Blob。
Blob 模型存储附件元数据(文件名、内容类型等)以及它们在存储服务中的标识符键。Blob 模型不存储实际的二进制数据。它们的精神是不可变的。一个文件,一个 blob。您也可以将同一个 blob 与多个应用程序模型关联。如果您想对给定的 Blob 进行转换,那么您的想法是创建一个新的 blob,而不是尝试修改现有的 blob(当然,如果您不需要,以后也可以删除之前的版本)。
安装¶ ↑
运行 bin/rails active_storage:install 来复制 active_storage 迁移。
注意:如果找不到任务,请验证 config/application.rb 中是否包含 require "active_storage/engine"。
示例¶ ↑
单个附件
class User < ApplicationRecord # Associates an attachment and a blob. When the user is destroyed they are # purged by default (models destroyed, and resource files deleted). has_one_attached :avatar end # Attach an avatar to the user. user.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpeg") # Does the user have an avatar? user.avatar.attached? # => true # Synchronously destroy the avatar and actual resource files. user.avatar.purge # Destroy the associated models and actual resource files async, via Active Job. user.avatar.purge_later # Does the user have an avatar? user.avatar.attached? # => false # Generate a permanent URL for the blob that points to the application. # Upon access, a redirect to the actual service endpoint is returned. # This indirection decouples the public URL from the actual one, and # allows for example mirroring attachments in different services for # high-availability. The redirection has an HTTP expiration of 5 min. url_for(user.avatar) class AvatarsController < ApplicationController def update # params[:avatar] contains an ActionDispatch::Http::UploadedFile object Current.user.avatar.attach(params.require(:avatar)) redirect_to Current.user end end
多个附件
class Message < ApplicationRecord has_many_attached :images end
<%= form_with model: @message, local: true do |form| %> <%= form.text_field :title, placeholder: "Title" %><br> <%= form.textarea :content %><br><br> <%= form.file_field :images, multiple: true %><br> <%= form.submit %> <% end %>
class MessagesController < ApplicationController def index # Use the built-in with_attached_images scope to avoid N+1 @messages = Message.all.with_attached_images end def create message = Message.create! params.expect(message: [ :title, :content, images: [] ]) redirect_to message end def show @message = Message.find(params[:id]) end end
图像附件的 Variation
<%# Hitting the variant URL will lazy transform the original blob and then redirect to its new service location %> <%= image_tag user.avatar.variant(resize_to_limit: [100, 100]) %>
File 服务策略¶ ↑
Active Storage 支持两种文件服务方式:重定向和代理。
重定向¶ ↑
Active Storage 会为文件生成稳定的应用程序 URL,访问这些 URL 会重定向到已签名的、短期有效的服务 URL。这减轻了应用程序服务器的服务文件数据的负担。这是默认的文件服务策略。
如果应用程序默认配置为代理文件,请使用 rails_storage_redirect_path 和 _url 路由助手来重定向。
<%= image_tag rails_storage_redirect_path(@user.avatar) %>
代理¶ ↑
还可以选择代理文件。这意味着您的应用程序服务器将在响应请求时从存储服务下载文件数据。这对于从 CDN 提供文件很有用。
您可以将 Active Storage 配置为默认使用代理
# config/initializers/active_storage.rb Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy
如果您想显式代理特定附件,可以使用 rails_storage_proxy_path 和 rails_storage_proxy_url 形式的 URL 助手。
<%= image_tag rails_storage_proxy_path(@user.avatar) %>
直接上传¶ ↑
Active Storage 及其附带的 JavaScript 库支持直接从客户端上传到云端。
直接上传安装¶ ↑
-
在应用程序的 JavaScript 包中包含 Active Storage JavaScript,或直接引用它。
直接通过 importmap-rails 而非 asset pipeline 在应用程序 HTML 中包含并自动启动
<%= javascript_include_tag "activestorage" %>
通过 importmap-rails 而非 asset pipeline 在应用程序 HTML 中通过 ESM 形式导入,不自动启动
# config/importmap.rb pin "@rails/activestorage", to: "activestorage.esm.js"
<script type="module-shim"> import * as ActiveStorage from "@rails/activestorage" ActiveStorage.start() </script>
使用 asset pipeline
//= require activestorage
使用 npm 包
import * as ActiveStorage from "@rails/activestorage" ActiveStorage.start()
-
用直接上传 URL 注释文件输入。
<%= form.file_field :attachments, multiple: true, direct_upload: true %>
-
在第三方存储服务上配置 CORS 以允许直接上传请求。
-
就是这样!表单提交后即可开始上传。
直接上传 JavaScript 事件¶ ↑
| 事件名称 | 事件目标 | 事件数据 (event.detail) |
描述 |
|---|---|---|---|
direct-uploads:start |
<form> |
无 | 包含直接上传字段文件的表单已提交。 |
direct-upload:initialize |
<input> |
{id, file} |
为表单提交后的每个文件触发。 |
direct-upload:start |
<input> |
{id, file} |
开始一个直接上传。 |
direct-upload:before-blob-request |
<input> |
{id, file, xhr} |
在向应用程序请求直接上传元数据之前。 |
direct-upload:before-storage-request |
<input> |
{id, file, xhr} |
在发出存储文件请求之前。 |
direct-upload:progress |
<input> |
{id, file, progress} |
在存储文件请求的进度中。 |
direct-upload:error |
<input> |
{id, file, error} |
发生错误。除非取消此事件,否则将显示一个 alert。 |
direct-upload:end |
<input> |
{id, file} |
一个直接上传已结束。 |
direct-uploads:end |
<form> |
无 | 所有直接上传均已结束。 |
许可证¶ ↑
Active Storage 在 MIT 许可证 下发布。
支持¶ ↑
API 文档位于:
Ruby on Rails 项目的错误报告可在此处提交:
功能请求应在此处的 rubyonrails-core 论坛上讨论:
- 模块 ActiveStorage::Blobs
- 模块 ActiveStorage::DisableSession
- 模块 ActiveStorage::Reflection
- 模块 ActiveStorage::Representations
- 模块 ActiveStorage::SetCurrent
- 模块 ActiveStorage::Streaming
- 模块 ActiveStorage::Transformers
- 模块 ActiveStorage::VERSION
- 类 ActiveStorage::AnalyzeJob
- 类 ActiveStorage::Analyzer
- 类 ActiveStorage::Attached
- 类 ActiveStorage::Attachment
- 类 ActiveStorage::BaseController
- 类 ActiveStorage::BaseJob
- 类 ActiveStorage::Blob
- 类 ActiveStorage::DirectUploadsController
- 类 ActiveStorage::DiskController
- 类 ActiveStorage::Error
- 类 ActiveStorage::FileNotFoundError
- 类 ActiveStorage::Filename
- 类 ActiveStorage::FixtureSet
- 类 ActiveStorage::IntegrityError
- 类 ActiveStorage::InvariableError
- 类 ActiveStorage::MirrorJob
- 类 ActiveStorage::Preview
- 类 ActiveStorage::PreviewError
- 类 ActiveStorage::PreviewImageJob
- 类 ActiveStorage::Previewer
- 类 ActiveStorage::PurgeJob
- 类 ActiveStorage::Service
- 类 ActiveStorage::TransformJob
- 类 ActiveStorage::UnpreviewableError
- 类 ActiveStorage::UnrepresentableError
- 类 ActiveStorage::Variant
- 类 ActiveStorage::VariantRecord
- 类 ActiveStorage::VariantWithRecord
- 类 ActiveStorage::Variation
- G
- V
类公共方法
gem_version() 链接
返回当前加载的 Active Storage 版本,作为 Gem::Version。
来源: 显示 | 在 GitHub 上
# File activestorage/lib/active_storage/gem_version.rb, line 5 def self.gem_version Gem::Version.new VERSION::STRING end
version() 链接
返回当前加载的 Active Storage 版本,作为 Gem::Version。
来源: 显示 | 在 GitHub 上
# File activestorage/lib/active_storage/version.rb, line 7 def self.version gem_version end