【问题标题】:How to add a custom service to ActiveStorage如何向 ActiveStorage 添加自定义服务
【发布时间】:2018-06-10 09:53:00
【问题描述】:

我想向 ActiveStorage 添加自定义服务,因为我想覆盖 ActiveStorage::Service::S3Service 服务的 url 方法,以便可以在我的 S3 存储桶前使用 CloudFront CDN。我想我不需要presigned_url 参数,我只需要密钥,因为 CloudFront 实例将拥有对 S3 存储桶的完全读取权限。

【问题讨论】:

    标签: ruby-on-rails amazon-web-services rails-activestorage


    【解决方案1】:

    在子类ActiveStorage::Service::S3ServiceActiveStorage::Service 命名空间中添加一个类。覆盖要覆盖的方法。例如:

    # lib/active_storage/service/cloudfront_s3_service.rb 
    require "active_storage/service/s3_service"
    
    class ActiveStorage::Service::CloudfrontS3Service < ActiveStorage::Service::S3Service
      def url(key, **)
        # ...
      end
    end
    

    请参阅config/storage.yml 中的自定义服务:

    production:
      service: CloudfrontS3
      access_key_id: ""
      secret_access_key: ""
      region: ""
      bucket: ""
    

    【讨论】:

    • 感谢您的回答@george,我只是想知道为什么 DiskService 使用从密钥派生的目录,而 S3 不使用?
    • @PRWhitehead,大多数现代文件系统不限制单个目录中的文件数量,但有些文件系统会遇到包含超过 30,000 个文件的目录的性能问题,这使得通过前缀删除、系统维护、备份等。
    • 感谢您的解释以及您在 ActiveStorage 上花费的时间。
    • 这有点含糊,缺少rails 6的一些细节。rails 6中的过程有点不同。
    • 在 Rails 6 上,我不得不偶然发现解决方案,因为 Zeitwork 在流程中添加了一些步骤。自定义服务必须存在于指定的命名空间(active_storage/service)中,其他任何地方都会产生意想不到的结果。您还需要在 application.rb 中指定服务并添加加载文件的路径config.active_storage.service = :cloudfront_s3 config.eager_load_paths &lt;&lt; Rails.root.join('lib', 'active_storage', 'service') 最后,您需要将类存根添加到新服务class CloudfrontS3Service &lt; ActiveStorage::Service::S3Service; end
    【解决方案2】:

    对于任何感兴趣的人,我有一个类似的问题,我想使用 S3Service 使用的相同平面单桶存储。一旦你知道如何,它就足够简单了:

    require "active_storage/service/disk_service"
    
    # S3 uses a flat folder structure, so mimic that so we an sync files and databases
    module ActiveStorage
      class Service
        class FlatDiskService < DiskService
          private
    
          def folder_for(_key)
            "/"
          end
        end
      end
    end
    

    配置如下:

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

    编辑:我已经用 Rails 6 中的修正版本更新了答案。

    【讨论】:

    • 请注意,Rails 6 的功能远不止这些
    • 您能否发布一些代码,以便我们可以看到差异,因为上面的示例一直在使用 Rails 5 和 6
    • 那么问题是在哪里这个文件存在,以及它是如何包含的。如果它在lib 中(就像大多数在线示例显示的那样),那么 Zeitwerk 会抱怨您的文件没有定义预期的 const。我可能做错了什么,但我看到的在线示例都没有完全解释所需的一切。将实现细节留给解释。
    • 见我上面的其他评论。 Zeitwerk 错误是通过将文件添加到配置中的 eager_load 路径引入的,删除它可以解决问题。
    猜你喜欢
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 1970-01-01
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多