使用 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。所以在 Cyber​​duck 中我看到了这样的东西: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

如果有人有更好的方法来做到这一点,我会很高兴:)