Тип ХранилищеЗначения в 1С 8.3: файлы, картинки и коллекции внутри базы
Содержание
Хранилище значений в 1С 8.3 — это тип данных ХранилищеЗначения, который упаковывает любое сериализуемое значение (файл, картинку, таблицу значений, структуру) в двоичный блок и сохраняет его в реквизите объекта базы. Записывают его через конструктор Новый ХранилищеЗначения(Значение), читают методом Получить().
Чаще всего с ним сталкиваются, когда нужно положить в справочник фото товара, скан договора или настройки обработки, а реквизит типа «Двоичные данные» в конфигураторе выбрать нельзя. Хранилище решает задачу за пару строк кода, но у него есть цена: рост базы, медленное открытие форм и данные, по которым нельзя искать запросом. Решение о том, что класть в реквизит, а что выносить на диск, лучше принять до того, как в справочнике окажутся тысячи файлов.
Как устроено хранилище значений и зачем оно нужно
Хранилище значений — это не подсистема и не отдельная база. Это обычный тип реквизита, такой же, как Строка или Число. Его можно выбрать у реквизита справочника, документа, регистра сведений, табличной части.
Что происходит при записи:
- 📦 Платформа сериализует значение во внутренний формат.
- 🗜️ Если передан объект
СжатиеДанных, результат сжимается. - 💾 Двоичный блок пишется в поле таблицы СУБД. В клиент-серверной базе это поле двоичного типа, в файловой — внутри файла
1Cv8.1CD.
При чтении Получить() выполняет обратное преобразование и возвращает исходное значение того же типа.
Что можно положить в хранилище
- ✅
ДвоичныеДанные— файлы любого формата: PDF, JPG, XLSX, архивы. - ✅
Картинка,ТабличныйДокумент,ТекстовыйДокумент. - ✅ Коллекции:
ТаблицаЗначений,ДеревоЗначений,Структура,Соответствие,Массив,СписокЗначений. - ✅ Примитивные типы и ссылки на объекты базы.
- ❌ Несериализуемые значения:
COMОбъект, формы, открытые потоки чтения и записи, объекты внешних соединений.
Где этот тип встречается в типовых конфигурациях
В БП 3.0, ЗУП 3.1 и УТ 11 хранилище значений используется в нескольких местах:
- 🖼️ присоединённые файлы, если они хранятся в базе, а не на томах на диске;
- ⚙️ сохранённые настройки отчётов и обработок;
- 🔐 служебные данные подсистем БСП, например безопасное хранилище паролей.
Не путайте с похожими терминами
| Термин | Что это на самом деле |
|---|---|
Хранилище значений (ХранилищеЗначения) | Тип данных реквизита для произвольного значения |
| Хранилище конфигурации | Сервис групповой разработки: захват и помещение объектов конфигурации |
Хранилище настроек (ХранилищеОбщихНастроек и др.) | Механизм сохранения пользовательских настроек форм и отчётов |
| Временное хранилище | Память сеанса; данные живут до закрытия формы или сеанса |
Если вы пришли с вопросом про захват объектов в конфигураторе — это хранилище конфигурации, тема другая.
Хранилище значений против других способов хранения
Хранить файл или сложную структуру можно минимум четырьмя способами. Каждый хорош в своей ситуации.
| Способ | Когда подходит | Минусы |
|---|---|---|
Реквизит ХранилищеЗначения | Файлы до нескольких мегабайт, настройки, коллекции, которые надо держать рядом с объектом | Растёт размер базы, нельзя искать и фильтровать по содержимому |
Строка неограниченной длины + ЗначениеВСтрокуВнутр() | Нужно видеть данные текстом, например при отладке | Текст занимает больше места, формат внутренний и меняться может |
| Файлы на диске (тома хранения) | Тысячи сканов и больших файлов, база должна оставаться компактной | Резервная копия базы не содержит файлов, нужен отдельный бэкап каталога |
| Внешняя СУБД или файловое хранилище | Архивы на десятки гигабайт, интеграции | Отдельная инфраструктура и права |
Сравнение с файловой системой
Главный плюс хранилища значений — целостность. Файл лежит в той же транзакции, что и объект. Записали документ — записался и скан. Выгрузили .dt — файлы уехали вместе с базой.
Минус — объём. База на 5 ГБ с 30 ГБ сканов внутри дольше копируется, дольше выгружается в .dt и тяжелее восстанавливается.
Практичное правило: настройки, шаблоны и небольшие картинки держите в хранилище значений. Сканы первички и всё, что растёт каждый день, выносите на тома на диске.
Сравнение с SQL-полями
В SQL такой реквизит выглядит как поле двоичного типа. Прочитать его средствами СУБД бессмысленно: внутри внутренний формат 1С, а не исходный файл. Поэтому прямые SQL-выгрузки содержимого хранилища не работают — данные достают только кодом 1С.
Права доступа к данным в хранилище значений
Отдельного права «на хранилище значений» в ролях нет. Доступ определяется правами на объект, у которого есть этот реквизит.
Как это работает на практике:
- 👤 Пользователь с правом
Чтениесправочника может прочитать и реквизит-хранилище, если код формы его получает. - ✏️ Право
Изменениепозволяет записать новое значение. - 🧩 В роли можно ограничить интерактивные права
ПросмотриРедактированиена уровне отдельного реквизита. Тогда пользователь не увидит поле на форме. - 🛡️ Ограничение доступа на уровне записей (RLS) действует на всю запись целиком, включая хранилище.
Интерактивные права на реквизит не защищают от серверного кода. Процедура, выполняемая в привилегированном режиме, прочитает хранилище у любого пользователя.
Пароли и токены — не в обычный реквизит
Частая ошибка доработок: пароль от сервиса кладут в хранилище значений реквизита справочника «Организации» и считают, что он спрятан. Его прочитает любой, у кого есть право чтения справочника и обработка из пары строк.
В конфигурациях на БСП для этого есть безопасное хранилище: функции ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище() и ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(). Данные лежат в отдельном регистре, доступном только в привилегированном режиме.
Работа с хранилищем значений из кода и формы
Запись и чтение на сервере
Базовые операции занимают две строки:
// Запись с максимальным сжатием
Объект.Настройки = Новый ХранилищеЗначения(ТаблицаНастроек, Новый СжатиеДанных(9));
// Чтение
ТаблицаНастроек = Объект.Настройки.Получить();
Уровень сжатия — от 0 до 9. Хорошо сжимаются тексты, XML, таблицы значений. JPG, PNG, PDF и архивы уже сжаты, на них выигрыш близок к нулю, а время записи растёт.
Картинка на управляемой форме
Тип ХранилищеЗначения недоступен в тонком и веб-клиенте. Поэтому напрямую привязать реквизит объекта к полю картинки нельзя. Рабочая схема — через временное хранилище:
- При чтении объекта на сервере достаём двоичные данные и кладём их во временное хранилище.
- Адрес сохраняем в реквизит формы типа
Строкаи привязываем к нему поле картинки. - Перед записью забираем данные по адресу и упаковываем их в хранилище значений.
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ДанныеКартинки = ТекущийОбъект.Фото.Получить();
Если ТипЗнч(ДанныеКартинки) = Тип("ДвоичныеДанные") Тогда
АдресКартинки = ПоместитьВоВременноеХранилище(ДанныеКартинки, УникальныйИдентификатор);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Если ЭтоАдресВременногоХранилища(АдресКартинки) Тогда
ДанныеКартинки = ПолучитьИзВременногоХранилища(АдресКартинки);
Если ТипЗнч(ДанныеКартинки) = Тип("ДвоичныеДанные") Тогда
ТекущийОбъект.Фото = Новый ХранилищеЗначения(ДанныеКартинки);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Файл с компьютера пользователя попадает во временное хранилище через стандартный диалог помещения файла на сервер. Он возвращает адрес — его и записывайте в АдресКартинки.
Не делайте ТекущийОбъект.Фото = ... в обработчике ПриЗаписиНаСервере: в этот момент объект уже записывается, и изменение реквизита в базу не попадёт.
Хранилище значений в запросах
В запросе поле-хранилище можно выбрать: в результате придёт значение типа ХранилищеЗначения, у которого затем вызывают Получить().
Нельзя:
- ❌ сравнивать поле в условии
ГДЕ; - ❌ упорядочивать и группировать по нему;
- ❌ соединять таблицы по этому полю.
Если нужно искать объекты, у которых файл заполнен, заведите рядом булев реквизит-признак или реквизит с именем файла и фильтруйте по нему. Тот же приём выручает для отчётов: размер файла в байтах, его расширение и дату загрузки удобно хранить в обычных реквизитах рядом с хранилищем и заполнять в момент записи.
Обмен и выгрузка
Хранилище значений корректно переносится через .dt, правила обмена и XDTO-сериализацию: в XML оно уходит как Base64-блок. Через «Выгрузку/загрузку данных XML» тоже переносится, но файл обмена получается тяжёлым.
Производительность и ограничения хранилища значений
Что тормозит
- 🐢 Чтение объекта целиком.
Ссылка.ПолучитьОбъект()и открытие формы элемента читают все реквизиты, включая хранилище. Справочник номенклатуры с фото по 8 МБ в каждом элементе открывается заметно дольше. - 🐢 Получение в цикле. 1000 вызовов
Получить()по 2 МБ — это 2 ГБ, прошедших через память рабочего процесса. - 🐢 Рост базы. Каждый перезаписанный файл раздувает таблицу; место в СУБД освобождается не сразу.
Динамический список не читает поле-хранилище, если оно не выведено в колонки. Поэтому список открывается быстро, а форма элемента — медленно. Это нормальное поведение.
Как не упереться в ограничения
- 📐 Держите большие файлы не в реквизите основного объекта, а в отдельном регистре сведений или справочнике-«файлохранилище». Основной объект тогда читается быстро.
- 🧮 Проверяйте размер перед записью:
ДанныеКартинки.Размер()возвращает число байт. Отсекайте файлы больше, например, 10 МБ. - 🗜️ Сжимайте только то, что сжимается: тексты и коллекции.
- 🗂️ Когда сканов станет много, переведите хранение файлов на тома. В типовых конфигурациях на БСП это делается в разделе
Администрированиев настройках работы с файлами.
Жёсткий предел задаёт СУБД: двоичное поле в MS SQL Server вмещает до 2 ГБ, в PostgreSQL — до 1 ГБ. На практике проблемы начинаются гораздо раньше: значение целиком загружается в оперативную память при каждом чтении.
Как найти, какое хранилище раздуло базу
В клиент-серверной базе:
- Посмотрите размеры таблиц средствами СУБД и найдите самые большие.
- Сопоставьте имя таблицы с объектом метаданных функцией
ПолучитьСтруктуруХраненияБазыДанных(). Она возвращает таблицу соответствий «объект 1С → таблица и поля СУБД». - По найденному реквизиту оцените, что и зачем туда пишется: часто это журнал или настройки, которые разрастаются без очистки.
Массовая очистка хранилищ — это изменение данных. Сделайте резервную копию базы перед удалением или перезаписью значений. Обработку запускайте в нерабочее время: она блокирует записываемые объекты.
Диагностика ошибок хранилища значений
Большинство проблем с этим типом — не сбои платформы, а ошибки в коде формы или в логике записи.
Если ошибка воспроизводится только у одного пользователя
Проверьте права. Пользователь без интерактивного права Просмотр на реквизит не увидит поле, а без права Изменение объекта не сможет записать новое значение. В журнале регистрации ошибка записи будет связана с нарушением прав доступа.
Частые вопросы
Можно ли создать реквизит типа «Двоичные данные» вместо хранилища значений?
ХранилищеЗначения. Двоичные данные кладут внутрь него.Как выгрузить файл из хранилища значений на диск?
Получить(), получите ДвоичныеДанные и сохраните их методом Записать(). Если файл нужен пользователю, поместите данные во временное хранилище и передайте адрес на клиент для скачивания.Попадает ли содержимое хранилища в резервную копию .dt?
.dt не попадают.Можно ли хранить в нём ссылки на документы?
Есть ли смысл сжимать фото в хранилище?
СжатиеДанных почти не уменьшит размер, но замедлит запись. Сжимайте тексты, XML и таблицы значений.