#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. Хорошо, похоже, я понял цель вашего вопроса по-другому 🙂 В любом случае, вы нашли ответ?