使用 Amazon S3 的 Active Storage 不使用指定的文件名保存,而是使用文件密钥
Active Storage with Amazon S3 not saving with filename specified but using file key instead
我在使用 Active Storage 时遇到问题。当我上传到 Amazon S3 时,我没有使用 myfile.zip
之类的原始名称将文件保存在存储桶中,而是将其保存为与该文件关联的 key
。所以在 Cyberduck 中我看到了这样的东西:5YE1aJQuFYyWNr6BSHxhQ48t
。没有任何文件扩展名。
我不确定 Rails 5 中是否有某些设置,或者它是否在 Amazon S3 中,但我花了几个小时谷歌搜索以找出发生这种情况的原因。
任何指点将不胜感激!
此致,
安德鲁
这是设计使然,来自 ActiveStorage。该文件由它的密钥存储并且在 S3 上没有扩展名,但是当 URL 由 ActiveStorage 生成时,disposition and filename are set.
def url(key, expires_in:, filename:, disposition:, content_type:)
instrument :url, key: key do |payload|
generated_url = object_for(key).presigned_url :get, expires_in: expires_in.to_i,
response_content_disposition: content_disposition_with(type: disposition, filename: filename),
response_content_type: content_type
payload[:url] = generated_url
generated_url
end
结束
这样做可能是为了避免您 运行 遇到的文件名转义问题。
您可以阅读有关 Content-Disposition
headers here 的更多信息。
您仍然可以使用文件名访问器引用名称。
class User < ApplicationRecord
has_one_attached :photo
...
end
filename = User.first.photo.filename
为了在 S3 上拥有自定义文件名,您应该同时更新 blob.key
和 S3 上的名称。
活动存储使用 blob.key
作为远程图像路径和名称将图像上传到 S3。
对于我的用法,我只使用允许生成由 filename
终止的 key
的 Monkey 补丁更改了 'images variants' 的名称:
config/initializers/active_storate_variant.rb
:
ActiveStorage::Variant.class_eval do
def key
"variants/#{blob.key}/#{Digest::SHA256.hexdigest(variation.key)}/#{filename}"
end
end
因此,当我需要 public url 作为图像变体时,我只需调用 image.url('400x400')
我的图片模型是这样自定义的:
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
has_one_attached :picture
SIZES = { '400x400' => '400x400' }
def url(size)
return "https://placehold.it/#{size}" unless picture.attached?
'https://my_s3_subdomain.amazonaws.com/' +
picture.variant(resize: SIZES[size]).processed.key
end
...
end
如果有人有更好的方法来做到这一点,我会很高兴:)
我在使用 Active Storage 时遇到问题。当我上传到 Amazon S3 时,我没有使用 myfile.zip
之类的原始名称将文件保存在存储桶中,而是将其保存为与该文件关联的 key
。所以在 Cyberduck 中我看到了这样的东西:5YE1aJQuFYyWNr6BSHxhQ48t
。没有任何文件扩展名。
我不确定 Rails 5 中是否有某些设置,或者它是否在 Amazon S3 中,但我花了几个小时谷歌搜索以找出发生这种情况的原因。
任何指点将不胜感激!
此致, 安德鲁
这是设计使然,来自 ActiveStorage。该文件由它的密钥存储并且在 S3 上没有扩展名,但是当 URL 由 ActiveStorage 生成时,disposition and filename are set.
def url(key, expires_in:, filename:, disposition:, content_type:)
instrument :url, key: key do |payload|
generated_url = object_for(key).presigned_url :get, expires_in: expires_in.to_i,
response_content_disposition: content_disposition_with(type: disposition, filename: filename),
response_content_type: content_type
payload[:url] = generated_url
generated_url
end
结束
这样做可能是为了避免您 运行 遇到的文件名转义问题。
您可以阅读有关 Content-Disposition
headers here 的更多信息。
您仍然可以使用文件名访问器引用名称。
class User < ApplicationRecord
has_one_attached :photo
...
end
filename = User.first.photo.filename
为了在 S3 上拥有自定义文件名,您应该同时更新 blob.key
和 S3 上的名称。
活动存储使用 blob.key
作为远程图像路径和名称将图像上传到 S3。
对于我的用法,我只使用允许生成由 filename
终止的 key
的 Monkey 补丁更改了 'images variants' 的名称:
config/initializers/active_storate_variant.rb
:
ActiveStorage::Variant.class_eval do
def key
"variants/#{blob.key}/#{Digest::SHA256.hexdigest(variation.key)}/#{filename}"
end
end
因此,当我需要 public url 作为图像变体时,我只需调用 image.url('400x400')
我的图片模型是这样自定义的:
class Image < ApplicationRecord
belongs_to :imageable, polymorphic: true
has_one_attached :picture
SIZES = { '400x400' => '400x400' }
def url(size)
return "https://placehold.it/#{size}" unless picture.attached?
'https://my_s3_subdomain.amazonaws.com/' +
picture.variant(resize: SIZES[size]).processed.key
end
...
end
如果有人有更好的方法来做到这一点,我会很高兴:)