How to retrieve attachment url with Rails Active Storage with S3

我怕爱的太早我们不能终老 提交于 2019-11-27 14:58:34

问题


rails version 5.2

I have a scenario that I need to access the public url of Rails Active Storage with Amazon s3 to make a zip file with Sidekiq background job.

I am having difficulty getting the actual file url. I have tried following

rails_blob_url

but it gives me following

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

How do I access the real file url through sidekiq ?

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

I can access fine these on web interface but not within the sidekiq


回答1:


Use ActiveStorage::Blob#service_url. For example, assuming a Post model with a single attached header_image:

@post.header_image.service_url



回答2:


My use case was to upload images to S3 which would have public access for ALL images in the bucket so a job could pick them up later, regardless of request origin or URL expiry. This is how I did it. (Rails 5.2.2)

First, the default for new S3 bucked is to keep everything private, so to defeat that there are 2 steps.

  1. Add a wildcard bucket policy. In AWS S3 >> your bucket >> Permissions >> Bucket Policy
{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}
  1. In your bucket >> Permissions >> Public Access Settings, be sure Block public and cross-account access if bucket has public policies is set to false

Now you can access anything in your S3 bucket with just the blob.key in the url. No more need for tokens with expiry.

Second, to generate that URL you can either use the solution by @Christian_Butzke: @post.header_image.service.send(:object_for, @post.header_image.key).public_url

However, know that object_for is a private method on service, and if called with public_send would give you an error. So, another alternative is to use the service_url per @George_Claghorn and just remove any params with a url&.split("?")&.first. As noted, this may fail in localhost with a host missing error.

Here is my solution or an uploadable "logo" stored on S3 and made public by default:

#/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

Enjoy ^_^




回答3:


If you need all your files public then you must make public your uploads:

In file config/storage.yml

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

In the code

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

It will return something like: "https://foo.s3.amazonaws.com/bar/buz/2yoQMbt4NvY3gXb5x1YcHpRa"

It is public readable because of the config above.




回答4:


A bit late, but you can get the public URL also like this (assuming a Post model with a single attached header_image as in the example above):

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


来源:https://stackoverflow.com/questions/49791684/how-to-retrieve-attachment-url-with-rails-active-storage-with-s3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!