使用多个 Rails ActiveStorage 服务

Using Multiple Rails ActiveStorage Services

我正在使用 ActiveStorage 上传 PDF 和图像。由于一些隐私问题,PDF 需要存储在本地,而图像需要使用 Amazon S3 存储。但是,看起来 ActiveStorage 只支持为每个环境设置一种服务类型 (除非您使用镜像功能,在这种情况下它不能满足我的需要).

有没有办法在同一环境中使用不同的服务配置?例如,如果模型 has_one_attached pdf 它使用本地服务:

local:
  service: Disk
  root: <%= Rails.root.join("storage") %>

如果另一个型号has_one_attached image使用亚马逊服务:

amazon:
  service: S3
  access_key_id: ""
  secret_access_key: ""

抱歉,恐怕 Active Storage 不支持这个。

ActiveStorage 很棒,但如果您需要每个环境的多种服务类型,它目前不适合您(正如上面提到的 George Claghorn)。如果您需要其他选项,我使用 Shrine.

解决了这个问题

诀窍是在初始化程序中设置多个 'stores':

# config/initializers/shrine.rb

Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new('storage', prefix: 'uploads/cache'),
  pdf_files: Shrine::Storage::FileSystem.new('storage', prefix: 'uploads'),
  images: Shrine::Storage::S3.new(**s3_options)
}

然后在 each 上传器中使用 default_storage 插件(连接到给定模型)。请注意,除非您在 both 上传者中指定 default_storage,否则它不会工作:

class PdfFileUploader < Shrine
  plugin :default_storage, cache: :cache, store: :pdf_files
end

class ImageFileUploader < Shrine
  plugin :default_storage, cache: :cache, store: :images
end

Rails 6.1 现在支持这个。

根据 this article,您可以指定 service 用于每个 attached:

class MyModel < ApplicationRecord
  has_one_attached :private_document, service: :disk
  has_one_attached :public_document,  service: :s3
end