ActiveStorage - Safari 缓存附件

ActiveStorage - Safari cached Attachments

我使用带有默认磁盘服务的 ActiveStorage。我的 api returns 图像 URL 并且在前端 (Vue.js) 图像是通过 IMG 标签嵌入的。当我打开图像时 URL 图像显示正确。

render json: {
  image_url: rails_blob_path(user.photo, only_path: true),
  ....
}
<a :href="image_url">
  <img :src="image_url">
</a>

当我查看源代码时,Safari 一直在尝试调用旧的 URL。这在 5 分钟后不再可能。 我试图直接在初始化程序中设置 config.active_storage.service_urls_expire_in,但这没有效果:

# config/initializers/active_storage.rb
Rails.application.config.active_storage.service_urls_expire_in = 1.week

当我放置图片默认 rails 方式时,图片会变得不同 URL 而这不会过期:

image_tag(user.photo)
# => <img src=".../rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDRG9JYTJWNVNTSWhjM2w1WlhSbGNtMWxOVEJvWW1kdE1YRm9ObW96TjNvd2IzTjNjd1k2QmtWVU9oQmthWE53YjNOcGRHbHZia2tpYjJsdWJHbHVaVHNnWm1sc1pXNWhiV1U5SW1wdlkzSmZhV052Ymw5amFHRjBYMnB2WTNJdWFHbHNablJmWW14aGRTNXdibWNpT3lCbWFXeGxibUZ0WlNvOVZWUkdMVGduSjJwdlkzSmZhV052Ymw5amFHRjBYMnB2WTNJdWFHbHNablJmWW14aGRTNXdibWNHT3daVU9oRmpiMjUwWlc1MFgzUjVjR1ZKSWc1cGJXRm5aUzl3Ym1jR093WlUiLCJleHAiOiIyMDIwLTA3LTAzVDA5OjQ4OjQyLjc0NFoiLCJwdXIiOiJibG9iX2tleSJ9fQ==--d23e3bb8161f54cce48a3d13a60d906c18574569/user_photo.png" />
rails_blob_path(user.photo, only_path: true)
# => ".../rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBkQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--23e3b6283c346c75d7e6c1e769eacb6d428fec0e/user_photo.png"

我可以在 api 中使用 image_tag 的 URL 吗?

Ruby 版本: 2.7.0

Rails 版本: 6.0.2.2

我遇到了同样的问题,所以我以以下解决方案结束。

您的系统可能有所不同,因为我为每张图片都有一个图片模型,以便也能够将图片重复用于其他条目。

所以我向图像模型和 media 路由添加了一个唯一标记。
获取https://my-domain.com/media/thumb/V8sPcDSNmMqrCRybXYLVRpoR

media_controller:

def show
  return head :not_found if origin.blank?

  send_file path, type: origin.content_type, disposition: :inline
rescue ActionController::MissingFile, NoMethodError
  redirect_to fallback
end

private

def origin
  @origin ||= Image.find_by(token: params[:token])
end

def path
  @path ||= origin.local_path(params[:size])
end

...

图片:

...

def local_path(size = :medium)
  img = image_with_size(size)
  ActiveStorage::Blob.service.path_for(img.key) if img.present?
end

def content_type
   file.blob&.content_type || 'image/png'
end

...

image_with_size 只是 returns 请求的文件变体。
也许我的方法对你的系统也有帮助。

如果您需要获取服务 url 而不是表示 url(通过 url_forimage_tag),请使用 service_url 方法:

user.photo.service_url

对于变体:

user.photo.variant(resize_to_limit: [320, nil]).processed.service_url

processed 方法可确保创建应用于原件的变体转换并将其上传到服务。

如果您使用的是本地 Disk 服务,则应手动设置 ActiveStorage::Current.host,或者应将 ActiveStorage::SetCurrent 问题包含在调用该方法的自定义控制器中.

但是关于公开服务 url https://github.com/rails/rails/issues/31419 存在争议,Rails 建议使用 url_for(variant)