класс ActiveStorage::Blob
Объект Blob — это запись, содержащая метаданные о файле и ключе, указывающем на расположение этого файла на службе. Объекты Blob можно создавать двумя способами:
-
До загрузки файла на серверную сторону в службу, с помощью
create_and_upload!. В этом случае на сервере должен быть доступен перемотанныйioс содержимым файла. -
До непосредственной загрузки файла на клиентской стороне в службу, с помощью
create_before_direct_upload!.
Первый вариант не требует интеграции с JavaScript на клиентской стороне и может использоваться любыми другими серверными службами, работающими с файлами. Второй вариант быстрее, так как не использует собственный сервер как промежуточную точку для загрузки, и может работать с развертываниями, такими как Heroku, которые не предоставляют большого дискового пространства.
Объекты Blob предполагаются неизменяемыми, что касается ссылки на конкретный файл. Вы можете обновлять метаданные объекта Blob на последующем шаге, но не должны обновлять ключ или изменять загруженный файл. Если вам необходимо создать производный объект или изменить объект Blob, просто создайте новый объект Blob и удалите старый.
Константы
- INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7
- INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7
- MINIMUM_TOKEN_LENGTH
Публичные методы класса
# File activestorage/app/models/active_storage/blob.rb, line 151
def compose(blobs, 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(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 105
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 116 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 для получения подписанной URL-адреса для загрузки. Эта подписанная URL-адреса указывает на сгенерированный ключом объекта Blob. После отправки формы с прямой загрузкой объект Blob может быть связан с соответствующей записью с помощью подписанного идентификатора.
# File activestorage/app/models/active_storage/blob.rb, line 78 def find_signed(id, record: nil, purpose: :blob_id) super(id, purpose: purpose) end
Вы можете использовать подписанный идентификатор объекта Blob для ссылки на него на клиентской стороне, не опасаясь подмены. Это особенно полезно для прямых загрузок, когда клиентской стороне необходимо сослаться на объект Blob, который был создан перед загрузкой, при отправке формы.
Подписанный идентификатор также используется для создания стабильных URL-адресов для объекта Blob через BlobsController.
# File activestorage/app/models/active_storage/blob.rb, line 86 def find_signed!(id, record: nil, purpose: :blob_id) super(id, purpose: purpose) end
Работает так же, как find_signed, но вызовет исключение ActiveSupport::MessageVerifier::InvalidSignature, если signed_id истек, имеет несоответствие цели, относится к другой записи или был изменён. Также вызовет исключение ActiveRecord::RecordNotFound , если по валидному подписанному идентификатору не удаётся найти запись.
# File activestorage/app/models/active_storage/blob.rb, line 125 def generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH) SecureRandom.base36(length) end
Чтобы предотвратить проблемы с файловыми системами, нечувствительными к регистру, особенно в сочетании с базами данных, которые рассматривают индексы как чувствительные к регистру, все ключи объектов Blob будут содержать только символы алфавита base-36 и, следовательно, будут в нижнем регистре. Для поддержания такого же или более высокого уровня энтропии, как и в кодировке base-58, используемой `has_secure_token`, количество используемых байтов увеличивается с 24 до 28.
Публичные методы экземпляра
# File activestorage/app/models/active_storage/blob.rb, line 198
def audio?
content_type.start_with?("audio")
end Возвращает true, если content_type этого blob находится в диапазоне аудио, например, audio/mpeg.
# File activestorage/app/models/active_storage/blob.rb, line 343
def content_type=(value)
unless ActiveStorage.silence_invalid_content_types_warning
if INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7.include?(value)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
#{value} is not a valid content type, it should not be used when creating a blob, and support for it will be removed in Rails 7.1.
If you want to keep supporting this content type past Rails 7.1, add it to `config.active_storage.variable_content_types`.
Dismiss this warning by setting `config.active_storage.silence_invalid_content_types_warning = true`.
MSG
end
if INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7.include?(value)
ActiveSupport::Deprecation.warn(<<-MSG.squish)
#{value} is not a valid content type, it should not be used when creating a blob, and support for it will be removed in Rails 7.1.
If you want to keep supporting this content type past Rails 7.1, add it to `config.active_storage.content_types_to_serve_as_binary`.
Dismiss this warning by setting `config.active_storage.silence_invalid_content_types_warning = true`.
MSG
end
end
super
end # File activestorage/app/models/active_storage/blob.rb, line 184
def custom_metadata
self[:metadata][:custom] || {}
end # File activestorage/app/models/active_storage/blob.rb, line 188 def custom_metadata=(metadata) self[:metadata] = self[:metadata].merge(custom: metadata) end
# File activestorage/app/models/active_storage/blob.rb, line 318
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 278 def download(&block) service.download key, &block end
Загружает файл, связанный с этим blob. Если блок не задан, весь файл считывается в память и возвращается. Это будет использовать много оперативной памяти для очень больших файлов. Если блок задан, загрузка передается потоком и передается по частям.
# File activestorage/app/models/active_storage/blob.rb, line 283 def download_chunk(range) service.download_chunk key, range end
Загружает часть файла, связанного с этим blob.
# File activestorage/app/models/active_storage/blob.rb, line 180 def filename ActiveStorage::Filename.new(self[:filename]) end
Возвращает экземпляр ActiveStorage::Filename имени файла, который можно запрашивать для базового имени, расширения и очищенной версии имени файла, которую можно безопасно использовать в URL-адресах.
# File activestorage/app/models/active_storage/blob.rb, line 193
def image?
content_type.start_with?("image")
end Возвращает true, если content_type этого blob находится в диапазоне изображений, например, image/png.
# File activestorage/app/models/active_storage/blob.rb, line 172 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. Этот ключ не предназначен для прямого показа пользователю. Всегда ссылайтесь на blobs, используя signed_id или проверенную форму ключа.
# File activestorage/app/models/active_storage/blob.rb, line 300
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- и ID 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 326 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 334 def purge_later ActiveStorage::PurgeJob.perform_later(self) end
Помещает в очередь ActiveStorage::PurgeJob для вызова purge. Это рекомендуемый способ очистки blob из транзакции, обратного вызова Active Record или в любом другом сценарии реального времени.
# File activestorage/app/models/active_storage/blob.rb, line 339 def service services.fetch(service_name) end
Возвращает экземпляр сервиса, который может быть настроен глобально или для каждого вложения
# File activestorage/app/models/active_storage/blob.rb, line 228 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 223 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 164 def signed_id(purpose: :blob_id, expires_in: nil) super end
Возвращает подписанный ID для этого blob, который подходит для ссылки на стороне клиента без опасения подделки.
# File activestorage/app/models/active_storage/blob.rb, line 208
def text?
content_type.start_with?("text")
end Возвращает true, если content_type этого blob находится в диапазоне текста, например, text/plain.
# File activestorage/app/models/active_storage/blob.rb, line 255 def upload(io, identify: true) unfurl io, identify: identify upload_without_unfurling io end
Загружает io на сервис на key для этого blob. Blobs предназначены для того, чтобы быть неизменяемыми, поэтому вы не должны использовать этот метод после того, как файл уже был загружен, чтобы соответствовать blob. Если вы хотите создать производный blob, вы должны просто создать новый blob на основе старого.
Перед загрузкой мы вычисляем контрольную сумму, которая отправляется на сервис для проверки целостности при передаче. Если контрольная сумма не соответствует тому, что получает сервис, будет выброшено исключение. Мы также измеряем размер io и сохраняем его в byte_size в записи blob. Тип содержимого автоматически извлекается из io, если вы не укажете content_type и передадите identify как false.
Обычно вам вообще не нужно вызывать этот метод напрямую. Используйте вместо этого статический метод create_and_upload!. Если вы используете этот метод напрямую, убедитесь, что вы используете его на сохранившемся Blob, иначе данные другого blob могут быть перезаписаны на сервисе.
# File activestorage/app/models/active_storage/blob.rb, line 216
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 объекта blob в службе. Это возвращает постоянный URL для общедоступных файлов и возвращает временный URL для закрытых файлов. Закрытые файлы подписаны и не предназначены для общего доступа. Вместо этого URL должен быть доступен только как переадресация с устойчивого, возможно, аутентифицированного URL. Скрытие URL за переадресацией также позволяет изменять службы без обновления всех URL.
# File activestorage/app/models/active_storage/blob.rb, line 203
def video?
content_type.start_with?("video")
end Возвращает true, если тип содержимого этого blob находится в диапазоне видео, например, video/mp4.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.