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
Use ActiveStorage::Blob#service_url
. For example, assuming a Post
model with a single attached header_image
:
@post.header_image.service_url
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.
- 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/*"
}
]
}
- In your bucket >> Permissions >> Public Access Settings, be sure
Block public and cross-account access if bucket has public policies
is set tofalse
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 ^_^
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