Активное хранилище public_url не возвращает ключ / имя файла.расширение

#ruby-on-rails #rails-activestorage

#ruby-on-rails #rails-activestorage

Вопрос:

Опция public добавлена в активное хранилище в этом PR: https://github.com/rails/rails/pull/36729
В нем он четко говорит: «В общедоступной корзине структура каталогов /[key]/[filename]»

Это имеет смысл и именно то, что я хочу. Я хочу иметь возможность (например) отправить кому-нибудь ссылку по электронной почте и разрешить им загружать файл. Поэтому мне нужно filename.extension . Но когда я запускаю приложение Rails 6.1, у загрузок в мою корзину нет имени файла после них. Файлы действительно отображаются в моем ведре, но только как их ключ. Не ключ / имя файла.

 amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-1
  bucket: mybucket
  public: true
  

Загрузка работает нормально. Файлы загружаются и отображаются в моей корзине. Но в представлении <%= @user.avatar.url %> возвращает https://s3.amazonaws.com/mybucket/g3ci2umbfj6wkxyggx7arhekxfib , я хочу, чтобы он возвращался https://s3.amazonaws.com/mybucket/g3ci2umbfj6wkxyggx7arhekxfib/myfile.png
Меня это действительно раздражает, потому что в PR автор четко указывает, что общедоступные файлы сохраняются как key / filename.extension

Итак, вопрос: в Rails 6.1 url метод возвращает имя файла как часть пути или нет. И если нет, то почему автор говорит, что это так? И если нет, есть ли лучший способ, чем исправление key ?

Ответ №1:

TLDR:

 = link_to @user.avatar.filename, rails_blob_path(@user.avatar, disposition: "course.avatar"), target: :_blank
  

даст вам ссылку для скачивания, например https://corsego-production.s3.eu-central-1.amazonaws.com/3gbpl68kckpkyrbjoslsl254th0u?response-content-disposition=inlineamp;X-Amz-Security-Token=IQoJb3JpZ2luX2VjEGgaCmV1LBuuKkri8zL3ohM4h9STzhTsnavAgulrcpBavL0POXg==amp;X-Amz-Algorithm=AWS4-HMAC-SHA256amp;X-Amz-Date=20201002T170820Zamp;X-Amz-SignedHeaders=hostamp;X-Amz-Expires=300amp;X-Amz-Credential=ASIA5RINJ20201002/eu-central-1/s3/aws4_requestamp;X-Amz-Signature=0a205d713ebaa9d3ca9d62


@user.avatar.url не должен ничего возвращать!

@user.avatar предполагается, что возвращает что-то вроде #<ActiveStorage::Attached::One:0x00007f15986ee4c0>

При создании вложения с активным хранилищем следующие поля о вложении автоматически заполняются и сохраняются как active_storage_blobs :

   create_table "active_storage_blobs", force: :cascade do |t|
    t.string "key", null: false
    t.string "filename", null: false
    t.string "content_type"
    t.text "metadata"
    t.bigint "byte_size", null: false
    t.string "checksum", null: false
    t.datetime "created_at", null: false
    t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
  end
  

Допустим, вы загружаете изображение с активным хранилищем. Приведенная выше таблица будет заполнена следующим образом:

 Id: 1
Key: sy2y1ytw7zob6mwtnwc1552cdp5l
Filename: Screenshot 2020-10-02 125405.png
Content_type: image/png
Metadata: {"identified"=>true, "analyzed"=>true}
Byte_size: 1550
Checksum: mGPerbRMj6LXbPKhqKd4bA
  

Чтобы отобразить аватар пользователя в виде изображения, необходимо вызвать = image_tag @user.avatar

= rails_blob_url(@user.avatar) даст вам что-то вроде https://example.com/rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5fb10a9c8e9f2c4e7099eee21c1dc2ff0343c210/Screenshot 2020-10-02 125405.png

= @user.avatar даст вам что-то вроде #<ActiveStorage::Attached::One:0x00007f1589293dd0>

= url_for(@user.avatar) даст вам что-то вроде /rails/active_storage/blobs/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBCZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5fb10a9c8e9f2c4e7099eee21c1dc2ff0343c210/Screenshot 2020-10-02 125405.png

Вторая таблица в миграциях, созданных active_storage, такова:

   create_table "active_storage_attachments", force: :cascade do |t|
    t.string "name", null: false
    t.string "record_type", null: false
    t.bigint "record_id", null: false
    t.bigint "blob_id", null: false
    t.datetime "created_at", null: false
    t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
    t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
  end
  

по сути, он соединяет большой двоичный объект с определенной записью в вашем приложении (в основном avatar это a blob , @user the record , и они связаны через active_storage_attachments таблицу.

Таким образом, вы также можете выполнить следующие команды в методе @user.avatar:

 @user.avatar.name #Avatar
@user.avatar.record_type #User
@user.avatar.record_id #2 (user id)
@user.avatar.blob_id #1 (blob id)
  

введите описание изображения здесь

Теперь ниже приведен пример URL-адреса вышеупомянутого файла, хранящегося в AWS S3:
https://corsego-production.s3.eu-central-1.amazonaws.com/3gbpl68kckpkyrbjoslsl254th0u?response-content-disposition=inlineamp;X-Amz-Security-Token=IQoJb3JpZ2luX2VjEGgaCmRzBFAiBSJ2QIEqs1opj+uCR74CDMt67ueDTTQIhAOJGGy2wfmxmGUwpQe9cyc84ZhUhuWKHdVgTUctbtGrVKdinkpg0w7OikcyNYpnbq/efcTmEgRvIlPO+0itFxUr8mKUvnDYSuKkri8zL3ohM4h9STzhTsnavAgulrcpBavL0POXg==amp;X-Amz-Algorithm=AWS4-HMAC-SHA256amp;X-Amz-Date=20201002T170820Zamp;X-Amz-SignedHeaders=hostamp;X-Amz-Expires=300amp;X-Amz-Credential=ASIA5RINJLY2F20201002/eu-central-2/s3/aws4_requestamp;X-Amz-Signature=0a205d713ebaaa339ad4ee09db9dfe16986e69d3ca9d62

Посмотрите, как URL-адрес содержит секретный токен и время истечения срока действия? Рекомендуется не иметь постоянных URL-адресов для файлов.

PS При подключении AWS S3 к вашему приложению не забудьте добавить конфигурацию CORS: введите описание изображения здесь

Комментарии:

1. Это подробный ответ, но он не ответил на мой вопрос. Мой вопрос касается Rails 6.1 public service PR.

2. Хорошо, похоже, я понял цель вашего вопроса по-другому 🙂 В любом случае, вы нашли ответ?