класс ActiveStorage::Blob
Объект Active Storage Blob
Объект Blob — это запись, содержащая метаданные о файле и ключ, указывающий на местоположение этого файла на сервере. Объекты Blob могут быть созданы двумя способами:
-
Перед загрузкой файла на сервер в службу, с помощью
create_and_upload!. Для этой операции должен быть доступен перематываемыйioс содержимым файла на сервере. -
Перед прямой загрузкой файла клиентом в службу, с помощью
create_before_direct_upload!.
Первый вариант не требует интеграции с JavaScript на стороне клиента и может быть использован любым другим бэкенд-сервисом, работающим с файлами. Второй вариант быстрее, так как не использует собственный сервер в качестве промежуточного звена для загрузки, и может работать с такими развертываниями, как Heroku, которые не предоставляют большого дискового пространства.
Объекты Blob предназначены для неизменяемости в том, что касается их ссылки на конкретный файл. Вы можете обновлять метаданные объекта Blob в последующих операциях, но не должны обновлять ключ или изменять загруженный файл. Если вам нужно создать производный объект или каким-либо образом изменить объект Blob, просто создайте новый объект Blob и удалите старый.
Константы
- MINIMUM_TOKEN_LENGTH
Публичные методы класса
# File activestorage/app/models/active_storage/blob.rb, line 144
def compose(blobs, key: nil, filename:, content_type: nil, metadata: nil)
raise ActiveRecord::RecordNotSaved, "All blobs must be persisted." if blobs.any?(&:new_record?)
content_type ||= blobs.pluck(:content_type).compact.first
new(key: key, filename: filename, content_type: content_type, metadata: metadata, byte_size: blobs.sum(&:byte_size)).tap do |combined_blob|
combined_blob.compose(blobs.pluck(:key))
combined_blob.save!
end
end Объединяет несколько объектов Blob в один «составной» объект Blob.
# File activestorage/app/models/active_storage/blob.rb, line 95
def create_and_upload!(key: nil, io:, filename:, content_type: nil, metadata: nil, service_name: nil, identify: true, record: nil)
create_after_unfurling!(key: key, io: io, filename: filename, content_type: content_type, metadata: metadata, service_name: service_name, identify: identify).tap do |blob|
blob.upload_without_unfurling(io)
end
end Создаёт новый экземпляр объекта Blob и затем загружает содержимое указанного io в службу. Экземпляр объекта Blob будет сохранён перед началом загрузки, чтобы предотвратить перезапись другой загрузки из-за коллизий ключей. При указании типа контента, передайте identify: false для обхода автоматического определения типа контента.
# File activestorage/app/models/active_storage/blob.rb, line 106 def create_before_direct_upload!(key: nil, filename:, byte_size:, checksum:, content_type: nil, metadata: nil, service_name: nil, record: nil) create! key: key, filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type, metadata: metadata, service_name: service_name end
Возвращает сохранённый объект Blob без загрузки файла в службу. Этот объект Blob будет указывать на ключ, где ещё нет файла. Он предназначен для совместного использования с загрузкой на стороне клиента, которая сначала создаёт объект Blob для получения подписанной ссылки на загрузку. Эта подписанная ссылка указывает на ключ, сгенерированный объектом Blob. После отправки формы с использованием прямой загрузки объект Blob может быть связан с соответствующей записью с использованием подписанного идентификатора.
# File activestorage/app/models/active_storage/blob.rb, line 69 def find_signed(id, record: nil, purpose: :blob_id) super(id, purpose: purpose) end
Вы можете использовать подписанный идентификатор объекта Blob для ссылки на него на стороне клиента, не опасаясь подмены. Это особенно полезно для прямых загрузок, когда на стороне клиента нужно сослаться на объект Blob, созданный до самой загрузки перед отправкой формы.
Подписанный идентификатор также используется для создания стабильных URL-адресов для объекта Blob через контроллер Blobs.
# File activestorage/app/models/active_storage/blob.rb, line 76 def find_signed!(id, record: nil, purpose: :blob_id) super(id, purpose: purpose) end
Действует как find_signed, но сгенерирует исключение ActiveSupport::MessageVerifier::InvalidSignature если срок действия подписанного идентификатора истек, цель не соответствует или произошла подмена. Также сгенерирует исключение ActiveRecord::RecordNotFound если по данному подписанному идентификатору не найдена запись.
# File activestorage/app/models/active_storage/blob.rb, line 115 def generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH) SecureRandom.base36(length) end
Для предотвращения проблем с регистронезависимыми файловыми системами, особенно в сочетании с базами данных, которые рассматривают индексы как регистрозависимые, все ключи Blob будут содержать только алфавит символов base-36 и, следовательно, будут строчными. Для поддержания того же или большего уровня энтропии, что и в кодировании base-58, используемом has_secure_token, количество используемых байтов увеличивается до 28 с 24 по умолчанию.
# File activestorage/app/models/active_storage/blob.rb, line 38
scope :unattached, -> { where.missing(:attachments) }
Возвращает объекты Blob, которые не привязаны ни к одной записи.
Методы экземпляра общедоступного доступа
# File activestorage/app/models/active_storage/blob.rb, line 32 has_many :attachments
Возвращает связанные экземпляры ActiveStorage::Attachment.
# File activestorage/app/models/active_storage/blob.rb, line 212
def audio?
content_type.start_with?("audio")
end Возвращает true, если тип содержимого этого объекта blob находится в диапазоне аудио, например, audio/mpeg.
# File activestorage/app/models/active_storage/blob.rb, line 198
def custom_metadata
self[:metadata][:custom] || {}
end # File activestorage/app/models/active_storage/blob.rb, line 202 def custom_metadata=(metadata) self[:metadata] = self[:metadata].merge(custom: metadata) end
# File activestorage/app/models/active_storage/blob.rb, line 322
def delete
service.delete(key)
service.delete_prefixed("variants/#{key}/") if image?
end Удаляет файлы на сервисе, связанные с объектом blob. Это следует делать только в том случае, если объект blob также будет удален, или у вас будет существовать мёртвая ссылка. В большинстве случаев рекомендуется использовать методы purge и purge_later.
# File activestorage/app/models/active_storage/blob.rb, line 282 def download(&block) service.download key, &block end
Загружает файл, связанный с этим объектом blob. Если блок не задан, весь файл читается в память и возвращается. Это потребует значительного объёма оперативной памяти для очень больших файлов. Если блок задан, загрузка происходит потоком и возвращается частями.
# File activestorage/app/models/active_storage/blob.rb, line 287 def download_chunk(range) service.download_chunk key, range end
Загружает часть файла, связанного с этим объектом blob.
# File activestorage/app/models/active_storage/blob.rb, line 194 def filename ActiveStorage::Filename.new(self[:filename]) end
Возвращает экземпляр ActiveStorage::Filename имени файла, позволяющий получить имя файла без расширения, расширение и безопасную для использования в URL-адресах версию имени файла.
# File activestorage/app/models/active_storage/blob.rb, line 207
def image?
content_type.start_with?("image")
end Возвращает true, если тип содержимого этого объекта blob находится в диапазоне изображений, например, image/png.
# File activestorage/app/models/active_storage/blob.rb, line 186 def key # We can't wait until the record is first saved to have a key for it self[:key] ||= self.class.generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH) end
Возвращает ключ, указывающий на файл на сервисе, связанный с этим объектом blob. Ключ имеет формат безопасного токена из Rails в нижнем регистре. Например: xtapjjcjiudrlk3tmwyjgpuobabd. Данный ключ не предназначен для прямого отображения пользователю. Всегда ссылайтесь на объекты blob, используя signed_id или проверенную форму ключа.
# File activestorage/app/models/active_storage/blob.rb, line 304
def open(tmpdir: nil, &block)
service.open(
key,
checksum: checksum,
verify: !composed,
name: [ "ActiveStorage-#{id}-", filename.extension_with_delimiter ],
tmpdir: tmpdir,
&block
)
end Загружает blob в временный файл на диске. Возвращает временный файл.
Имя временного файла начинается с ActiveStorage- и идентификатора объекта blob. Его расширение соответствует расширению объекта blob.
По умолчанию временный файл создается в Dir.tmpdir. Чтобы создать его в другом каталоге, передайте tmpdir:.
blob.open(tmpdir: "/path/to/tmp") do |file| # ... end
Временный файл автоматически закрывается и удаляется после выполнения данного блока.
Вызывает исключение ActiveStorage::IntegrityError, если загруженные данные не соответствуют контрольной сумме объекта blob.
# File activestorage/app/models/active_storage/blob.rb, line 330 def purge destroy delete if previously_persisted? rescue ActiveRecord::InvalidForeignKey end
Удаляет запись объекта blob и затем удаляет файл на сервисе. Это рекомендуемый способ удаления ненужных объектов blob. Обратите внимание, что удаление файла с сервиса инициирует HTTP-соединение с сервисом, которое может быть медленным или недоступным, поэтому этот метод не следует использовать внутри транзакции или в обратных вызовах. Используйте purge_later вместо этого.
# File activestorage/app/models/active_storage/blob.rb, line 338 def purge_later ActiveStorage::PurgeJob.perform_later(self) end
Добавляет в очередь ActiveStorage::PurgeJob для вызова purge. Это рекомендуемый способ удаления объектов blob из транзакции, обратного вызова Active Record или в любой другой ситуации реального времени.
# File activestorage/app/models/active_storage/blob.rb, line 343 def service services.fetch(service_name) end
Возвращает экземпляр сервиса, который может быть настроен глобально или по каждому вложению.
# File activestorage/app/models/active_storage/blob.rb, line 242 def service_headers_for_direct_upload service.headers_for_direct_upload key, filename: filename, content_type: content_type, content_length: byte_size, checksum: checksum, custom_metadata: custom_metadata end
Возвращает Hash заголовков для запросов service_url_for_direct_upload.
# File activestorage/app/models/active_storage/blob.rb, line 237 def service_url_for_direct_upload(expires_in: ActiveStorage.service_urls_expire_in) service.url_for_direct_upload key, expires_in: expires_in, content_type: content_type, content_length: byte_size, checksum: checksum, custom_metadata: custom_metadata end
Возвращает URL-адрес, который может быть использован для прямой загрузки файла для данного объекта blob на сервис. Этот URL-адрес предназначен для кратковременного использования в целях безопасности и генерируется только по запросу со стороны клиентской JavaScript-стороны, ответственной за выполнение загрузки.
# File activestorage/app/models/active_storage/blob.rb, line 178 def signed_id(purpose: :blob_id, expires_in: nil, expires_at: nil) super end
Возвращает подписанный идентификатор для этого объекта blob, подходящий для использования на стороне клиента без опасений подделки.
# File activestorage/app/models/active_storage/blob.rb, line 222
def text?
content_type.start_with?("text")
end Возвращает true, если тип содержимого этого объекта blob находится в диапазоне текста, например, text/plain.
# File activestorage/app/models/active_storage/blob.rb, line 259 def upload(io, identify: true) unfurl io, identify: identify upload_without_unfurling io end
Загружает io в службу на key для этого блока. Блоки предназначены для неизменяемости, поэтому вы не должны использовать этот метод после того, как файл уже был загружен в блок. Если вы хотите создать производный блок, создайте новый блок на основе старого.
Перед загрузкой мы вычисляем контрольную сумму, которая отправляется в службу для проверки целостности транзита. Если контрольная сумма не соответствует полученной службой, будет вызвано исключение. Мы также измеряем размер io и сохраняем его в byte_size в записи блока. Тип контента автоматически извлекается из io , если вы не укажете content_type и не передадите identify как false.
Обычно вам не нужно вызывать этот метод напрямую. Используйте метод класса create_and_upload! вместо этого. Если вы все же используете этот метод напрямую, убедитесь, что используете его с постоянным Blob, иначе данные другого блока могут быть перезаписаны в службе.
# File activestorage/app/models/active_storage/blob.rb, line 230
def url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline, filename: nil, **options)
service.url key, expires_in: expires_in, filename: ActiveStorage::Filename.wrap(filename || self.filename),
content_type: content_type_for_serving, disposition: forced_disposition_for_serving || disposition, **options
end Возвращает URL блока в службе. Это возвращает постоянный URL для общедоступных файлов и возвращает краткосрочный URL для частных файлов. Частные файлы подписаны и не предназначены для публичного использования. Вместо этого URL должен быть показан только как переадресация со стабильного, возможно, аутентифицированного URL. Скрытие URL за переадресацией также позволяет вам изменять службы без обновления всех URL.
# File activestorage/app/models/active_storage/blob.rb, line 217
def video?
content_type.start_with?("video")
end Возвращает true, если тип контента этого блока находится в диапазоне видео, например, video/mp4.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.