В процессе разработки часто возникает задача автоматической генерации файлов (например, отчетов, логов или структур обмена в формате JSON) и их прикрепления к документам или справочникам. В современных конфигурациях на базе Библиотеки стандартных подсистем (БСП) механизм присоединенных файлов имеет сложную архитектуру, поэтому простая запись элемента в справочник часто приводит к ошибкам. В этой статье мы подробно разберем, как правильно сформировать JSON и поместить его в хранилище так, чтобы файл открывался и корректно отображался в интерфейсе системы.
Рассмотрим ситуацию: разработчик создает новый элемент в справочнике ЗаказКлиентаПрисоединенныеФайлы, заполняет реквизит ФайлХранилище строкой JSON и записывает объект. На первый взгляд всё верно, но при попытке открыть файл система выдает ошибку. Выясним причину этого поведения. В архитектуре БСП справочник «Присоединенные файлы» является лишь «оберткой» или карточкой файла. Сами двоичные данные (содержимое файла) хранятся либо в регистре сведений ДвоичныеДанныеФайлов, либо во внешних томах на диске сервера.
Если мы записываем данные только в справочник, игнорируя регистр сведений или механизмы работы с томами, стандартные команды «Открыть» или «Редактировать» не находят контента. Кроме того, прямая передача текстовой строки в реквизит типа ХранилищеЗначения без предварительной конвертации в двоичные данные часто приводит к повреждению структуры файла.
Для начала нам необходимо создать JSON-структуру. Чтобы избежать проблем с кодировками и блокировками файлов, проанализируем наиболее эффективный способ — формирование данных в оперативной памяти с последующей конвертацией в ДвоичныеДанные. Рассмотрим следующий код:
// 1. Создаем структуру данных
СтруктураДанных = Новый Структура;
СтруктураДанных.Вставить("ДатаФормирования", ТекущаяДата());
СтруктураДанных.Вставить("НомерЗаказа", Объект.Номер);
СтруктураДанных.Вставить("Статус", "Выгружено");
// 2. Сериализуем структуру в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыЗаписи = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Авто, Символы.Таб);
ЗаписьJSON.УстановитьСтроку(ПараметрыЗаписи);
ЗаписатьJSON(ЗаписьJSON, СтруктураДанных);
СтрокаJSON = ЗаписьJSON.Закрыть();
// 3. Преобразуем строку в двоичные данные (UTF-8 без BOM)
ДанныеФайла = ПолучитьДвоичныеДанныеИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, Ложь);
Обратите внимание на использование ПолучитьДвоичныеДанныеИзСтроки. Это позволяет нам сразу получить объект, готовый для сохранения в базу, минуя создание временных файлов на диске. Параметр Ложь в конце функции указывает на отсутствие метки BOM, что является стандартом для большинства современных интеграционных систем.
Вместо того чтобы вручную создавать элементы справочников и записи в регистрах, воспользуемся программным интерфейсом БСП. Модуль РаботаСФайлами содержит все необходимые инструменты. Проанализируем использование функции ПрисоединенныйФайлИзДвоичныхДанных. Этот метод берет на себя всю «черную работу»: создание элемента справочника, регистрацию данных в хранилище и привязку к владельцу.
Разберем реализацию по шагам:
// Предположим, СсылкаНаЗаказ — это ссылка на документ ЗаказКлиента
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("Автор", Пользователи.ТекущийПользователь());
ПараметрыФайла.Вставить("ИмяФайлаБезРасширения", "Data_Export_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd"));
ПараметрыФайла.Вставить("РасширениеБезТочки", "json");
ПараметрыФайла.Вставить("ДатаМодификацииУниверсальная", ТекущаяДата());
// Вызов стандартной функции БСП
НовыйФайлСсылка = РаботаСФайлами.ПрисоединенныйФайлИзДвоичныхДанных(СсылкаНаЗаказ, ПараметрыФайла, ДанныеФайла);
Если ЗначениеЗаполнено(НовыйФайлСсылка) Тогда
Сообщить("Файл успешно сохранен и прикреплен к заказу!");
КонецЕсли;
Этот подход гарантирует, что файл будет записан именно туда, куда указано в настройках системы (в базу или в том), и для него будут созданы все необходимые служебные записи. Вам не нужно знать точное имя справочника присоединенных файлов — система определит его автоматически по типу ссылки владельца.
Если по каким-то причинам вы не можете использовать РаботаСФайлами, рассмотрим, как правильно выполнить запись «вручную», чтобы избежать ошибок доступа и пустых файлов. Выясним причину ошибки «Нет доступа к файлу», которая часто упоминается на форумах. Она возникает, если объект ЗаписьJSON еще открыт в момент попытки чтения файла в ДвоичныеДанные. Всегда вызывайте Закрыть() перед использованием файла.
Алгоритм ручной записи должен выглядеть так:
...ПрисоединенныеФайлы.ДвоичныеДанныеФайлов (или ПрисоединенныеФайлы в старых версиях).Посмотрим на пример кода для ручной записи:
// Создаем карточку файла
НовыйФайл = Справочники.ЗаказКлиентаПрисоединенныеФайлы.СоздатьЭлемент();
НовыйФайл.Наименование = "ExportData.json";
НовыйФайл.ВладелецФайла = СсылкаДокПриход;
НовыйФайл.ДатаСоздания = ТекущаяДата();
НовыйФайл.Расширение = "json";
НовыйФайл.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВИнформационнойБазе;
НовыйФайл.Записать();
// Записываем данные в регистр сведений
МенеджерЗаписи = РегистрыСведений.ДвоичныеДанныеФайлов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Файл = НовыйФайл.Ссылка;
МенеджерЗаписи.ДвоичныеДанныеФайла = Новый ХранилищеЗначения(ДанныеФайла, Новый СжатиеДанных(9));
МенеджерЗаписи.Записать(Истина);
Важный нюанс: при ручном подходе вы берете на себя ответственность за корректность заполнения всех полей, включая размер файла и контрольные суммы, если они требуются логикой вашей конфигурации. Именно поэтому использование РаботаСФайлами предпочтительнее.
Проанализируем ситуации, когда что-то идет не так:
ПолучитьИмяВременногоФайла() и закрыли все потоки записи (ЗаписьJSON, ЗаписьТекста) перед созданием объекта ДвоичныеДанные.Закрыть() у объекта записи. Данные сбрасываются из буфера в поток только в этот момент.ВладелецФайла. Также убедитесь, что в конфигурации для данного справочника не настроены фильтры (например, по пометке удаления).Подводя итог, можно сказать, что наиболее надежным и современным способом является работа через ДвоичныеДанные и стандартные модули БСП. Это избавляет от необходимости манипулировать регистрами напрямую и гарантирует стабильную работу системы даже после обновлений платформы или конфигурации.