Blob и File: хранение бинарных данных

Idb-keyval — это лёгкая обёртка для IndexedDB, обеспечивающая простой интерфейс ключ–значение для хранения данных в браузере. Одним из наиболее мощных аспектов библиотеки является возможность работы с бинарными данными, представленными объектами Blob и File. Эти объекты позволяют сохранять и извлекать изображения, аудио, видео и другие типы файлов без необходимости их конвертации в строки или Base64.


Основные объекты Blob и File

Blob (Binary Large Object) — это контейнер для хранения бинарных данных. Он может содержать массивы байтов, строки, изображения и другие данные. Ключевые свойства и методы:

  • size — размер данных в байтах.
  • type — MIME-тип содержимого (image/png, application/pdf и т.д.).
  • slice(start, end) — создание нового Blob на основе части данных.
  • arrayBuffer() — получение ArrayBuffer для низкоуровневой работы с данными.
  • text() — получение текста из Blob (если это текстовые данные).

File — расширение Blob с дополнительными метаданными, такими как имя файла и дата последнего изменения:

  • name — имя файла.
  • lastModified — дата последнего изменения.
  • Наследует все методы и свойства Blob.

File часто создаётся через <input type="file"> или new File([...], "filename").


Сохранение Blob и File в Idb-keyval

Idb-keyval полностью поддерживает хранение Blob и File. Важно помнить, что IndexedDB позволяет хранить объекты, поддерживаемые структурированным клонированием (structuredClone), а это включает Blob и File.

Пример сохранения Blob:

import { set } from 'idb-keyval';

const imageBlob = new Blob([arrayBuffer], { type: 'image/png' });

set('profile-image', imageBlob)
  .then(() => console.log('Изображение сохранено'))
  .catch(err => console.error('Ошибка сохранения:', err));

Пример сохранения File:

import { set } from 'idb-keyval';

const fileInput = document.querySelector('input[type="file"]');

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];
  set('uploaded-file', file)
    .then(() => console.log('Файл сохранён'))
    .catch(err => console.error('Ошибка сохранения файла:', err));
});

Извлечение Blob и File из хранилища

При извлечении данных важно использовать правильное преобразование, если требуется работа с контентом.

Пример получения Blob:

import { get } from 'idb-keyval';

get('profile-image')
  .then(blob => {
    if (blob) {
      const url = URL.createObjectURL(blob);
      const img = document.createElement('img');
      img.src = url;
      document.body.appendChild(img);
    }
  })
  .catch(err => console.error('Ошибка извлечения:', err));

Пример получения File:

get('uploaded-file')
  .then(file => {
    if (file) {
      console.log('Имя файла:', file.name);
      console.log('Тип файла:', file.type);
      console.log('Размер файла:', file.size);
    }
  });

Манипуляции с бинарными данными после извлечения

После извлечения Blob или File можно выполнять различные операции:

  1. Чтение как ArrayBuffer:
file.arrayBuffer().then(buffer => {
  // buffer содержит бинарные данные файла
});
  1. Чтение как текст (для текстовых файлов):
blob.text().then(text => {
  console.log('Содержимое файла:', text);
});
  1. Создание URL для отображения:
const objectUrl = URL.createObjectURL(blob);
// Использовать objectUrl в <img>, <audio>, <video>
  1. Формирование нового Blob или File:
const newBlob = new Blob([blob], { type: 'image/jpeg' });
const newFile = new File([blob], 'copy.jpg', { type: 'image/jpeg' });

Особенности хранения больших файлов

  • Индексация и ключи: Каждый Blob или File хранится по уникальному ключу. При работе с большими файлами следует учитывать ограничения памяти браузера.
  • Асинхронность: Все операции с set и get асинхронные и возвращают промисы.
  • Поддержка MIME-типов: type сохраняется, что позволяет правильно интерпретировать данные при извлечении.
  • Сжатие и оптимизация: Idb-keyval не выполняет сжатие; для экономии памяти следует использовать внешние библиотеки для сжатия изображений или аудио перед сохранением.

Совместимость и ограничения

  • IndexedDB поддерживается всеми современными браузерами, поэтому Blob и File через Idb-keyval можно безопасно хранить на стороне клиента.
  • Некоторые старые браузеры могут ограничивать размер хранилища. Для очень больших данных рекомендуется использовать Chunking — деление Blob на части и сохранение их по отдельным ключам.
  • Необходимо контролировать доступ к памяти, особенно при множественных больших файлах, чтобы избежать ошибок QuotaExceededError.

Практические сценарии применения

  • Сохранение аватаров и изображений профиля для оффлайн-доступа.
  • Локальное кеширование медиафайлов для веб-приложений.
  • Временное хранение загруженных пользователем документов перед отправкой на сервер.
  • Сбор и обработка больших бинарных данных (например, сканированные документы или аудиозаписи) без необходимости немедленной загрузки на сервер.

Библиотека Idb-keyval превращает IndexedDB из сложной API в удобное хранилище ключ–значение, позволяя работать с Blob и File на высоком уровне, сохраняя все преимущества структурированного клонирования и асинхронной работы с бинарными данными.