web-dev-qa-db-ja.com

Rails Active Storage with S3を使用して添付URLを取得する方法

Rails version 5.2

SidekiqバックグラウンドジョブでZipファイルを作成するには、Amazon s3でRails Active StorageのパブリックURLにアクセスする必要があるシナリオがあります。

実際のファイルURLを取得するのが困難です。私はフォローしようとしました

Rails_blob_url

しかし、それは私に以下を与えます

http://localhost:3000/Rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--9598613be650942d1ee4382a44dad679a80d2d3b/sample.pdf

Sidekiqを介して実際のファイルのURLにアクセスするにはどうすればよいですか?

storage.yml

 test:
  service: Disk
  root: <%= Rails.root.join("tmp/storage") %>

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

development:
  service: S3
  access_key_id: 'xxxxx'
  secret_access_key: 'xxxxx'
  region: 'xxxxx'
  bucket: 'xxxxx'

development.rb

  config.active_storage.service = :development

私はWebインターフェイスでこれらにうまくアクセスできますが、sidekiq内ではできません

11
Shani

ActiveStorage::Blob#service_url を使用します。たとえば、単一のheader_imageが添付されたPostモデルを想定すると:

@post.header_image.service_url
34
George Claghorn

私のユースケースは、バケット内のすべての画像にパブリックアクセスできるS3に画像をアップロードして、リクエストのオリジンまたはURLの有効期限に関係なく、ジョブが後でそれらを取得できるようにすることでした。これが私がやった方法です。 (レール5.2.2)

最初に、新しいS3のデフォルトでは、すべてを非公開にして、2つのステップがあることを無効にします。

  1. ワイルドカードバケットポリシーを追加します。 AWS S3 >>バケット>>権限>>バケットポリシー
_{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}
_
  1. バケット>>権限>>パブリックアクセス設定で、_Block public and cross-account access if bucket has public policies_がfalseに設定されていることを確認してください

これで、URLの_blob.key_だけでS3バケット内のすべてにアクセスできます。期限切れのトークンはもう必要ありません。

第二に、そのURLを生成するには、@ Christian_Butzkeのソリューションを使用できます:@post.header_image.service.send(:object_for, @post.header_image.key).public_url

ただし、object_forはserviceのプライベートメソッドであり、public_sendを指定して呼び出すとエラーが発生することに注意してください。そのため、別の代替方法は、@ George_Claghornごとにservice_urlを使用し、url&.split("?")&.firstを持つすべてのパラメーターを削除することです。前述のように、これはローカルホストで失敗し、ホストが見つからないというエラーが発生する場合があります。

これが私のソリューション、またはS3に保存され、デフォルトで公開されているアップロード可能な「ロゴ」です。

_#/models/company.rb
has_one_attached :logo
def public_logo_url
    if self.logo&.attachment
        if Rails.env.development?
            self.logo_url = Rails.application.routes.url_helpers.Rails_blob_url(self.logo, only_path: true)
        else
            self.logo_url = self.logo&.service_url&.split("?")&.first
        end
    end
    #set a default lazily
    self.logo_url ||= ActionController::Base.helpers.asset_path("default_company_icon.png")
end
_

お楽しみください^ _ ^

4
genkilabs

すべてのファイルを公開する必要がある場合は、アップロードを公開する必要があります。

Config/storage.ymlファイル内

Amazon:
  service: S3
  access_key_id: zzz
  secret_access_key: zzz
  region: zzz
  bucket: zzz
  upload:
    acl: "public-read"

コード内

attachment = ActiveStorage::Attachment.find(90)
attachment.blob.service_url # returns large URI
attachment.blob.service_url.sub(/\?.*/, '') # remove query params

次のようなものが返されます: " https://foo.s3.amazonaws.com/bar/buz/2yoQMbt4NvY3gXb5x1YcHpRa "

上記の設定により、パブリックで読み取り可能です。

1
Aivils Štoss

少し遅れますが、次のような公開URLを取得することもできます(上記の例のように、head_imageが1つ添付されているPostモデルを想定しています)。

@post.header_image.service.send(:object_for, @post.header_image.key).public_url
0