При интеграции сторонних систем с 1С через протокол OData разработчики часто сталкиваются с неприятной особенностью: файлы, которые хранятся непосредственно в базе данных, передаются без проблем, но как только объем данных вынуждает администраторов перенести файлы в тома на диске, запросы к OData начинают возвращать пустые значения. В этой статье мы подробно разберем, почему это происходит, и как реализовать обходное решение, сохранив производительность системы.
Для начала проанализируем ситуацию с точки зрения архитектуры платформы. Когда мы обращаемся к справочнику ПрисоединенныеФайлы через OData, сервис обращается напрямую к таблицам базы данных (SQL или файловой СУБД). Рассмотрим два сценария хранения:
ХранилищеЗначения. OData умеет извлекать эти данные при использовании суффикса /$value.Проблема заключается в том, что OData-интерфейс 1С — это декларативный механизм. Он транслирует данные «как есть» из таблиц БД. Он не исполняет программный код конфигурации в момент запроса. Поскольку логика сборки пути к файлу и его чтение с диска реализованы на уровне встроенного языка (в модулях БСП), стандартный OData просто не знает, как «сходить» на диск и забрать файл. Для него это поле выглядит пустым или содержащим технический маркер.
Многие разработчики надеются найти «хитрый способ» настройки OData без изменения конфигурации. Однако, как показывает практика и обсуждения экспертов, таких способов в рамках стандартного интерфейса не существует. Рассмотрим, какие пути решения часто предлагают, и почему они могут не подойти:
Base64 строку. Однако OData не поддерживает динамическое вычисление таких полей «на лету» без записи в БД, что делает этот путь бессмысленным для оперативного получения данных.Самым эффективным и профессиональным способом решения задачи является создание собственного HTTP-сервиса. Этот подход позволяет нам использовать всю мощь встроенного языка 1С и механизмов Библиотеки стандартных подсистем (БСП). Разберем по шагам, как это реализовать.
Основное преимущество собственного сервиса в том, что мы можем вызвать стандартную функцию БСП РаботаСФайлами.ДвоичныеДанныеФайла(). Эта функция абсолютно универсальна: ей не важно, где физически лежит файл — в базе или в томе. Она сама определит местоположение, проверит права и вернет нам объект ДвоичныеДанные.
Предположим, нам нужно получить файл по его уникальному идентификатору (GUID). Проанализируем пример кода для метода GET нашего будущего сервиса.
Сначала создадим в конфигураторе новый объект HTTP-сервис, зададим ему имя (например, FileStorage) и шаблон URL вида /getfile/{ID}.
В модуле этого сервиса опишем функцию обработки запроса:
Функция ПолучитьФайлGet(Запрос)
// Извлекаем идентификатор файла из параметров URL
ИдентификаторФайла = Запрос.ПараметрыURL.Получить("ID");
СсылкаНаФайл = Справочники.Файлы.ПолучитьСсылку(Новый УникальныйИдентификатор(ИдентификаторФайла));
Если СсылкаНаФайл.Пустая() Тогда
Возврат Новый HTTPСервисОтвет(404);
КонецЕсли;
// Используем стандартный механизм БСП для получения данных
// Функция сама определит, лежит файл в томе или в базе
Попытка
ДанныеФайла = РаботаСФайлами.ДвоичныеДанныеФайла(СсылкаНаФайл);
Исключение
Возврат Новый HTTPСервисОтвет(500); // Ошибка доступа или отсутствие файла на диске
КонецПопытки;
// Формируем ответ. Можно вернуть чистые двоичные данные или Base64
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзДвоичныхДанных(ДанныеФайла);
Ответ.Заголовки.Вставить("Content-Type", "application/octet-stream");
Возврат Ответ;
КонецФункции
Проанализируем преимущества использования HTTP-сервиса в данной ситуации:
РаботаСФайлами.ДвоичныеДанныеФайла берет на себя всю рутину по работе с регистром ПутиКФайламВТомах.USR1CV8) имеет физический доступ к сетевым дискам. При прямом запросе через внешние инструменты вы могли бы столкнуться с проблемой прав доступа ОС.Base64, если внешняя система умеет принимать бинарный поток.Если перед вами стоит обратная задача — загрузить файл через OData так, чтобы он попал в том, — ситуация аналогичная. При использовании стандартного метода POST к сущности OData, платформа запишет данные в таблицу БД. Чтобы файл «улетел» в том, в конфигурации должны быть настроены правила перемещения (регламентное задание) или вызываться специфический программный код при записи. Использование собственного HTTP-сервиса для загрузки также является более надежным вариантом, так как позволяет сразу вызвать процедуру РаботаСФайлами.ЗаписатьФайл(), которая мгновенно отправит файл в нужный том согласно настройкам системы.
Резюме: Если ваша конфигурация (например, 1С:Документооборот) настроена на хранение файлов в томах, забудьте о стандартном OData для работы с бинарным контентом. Создание небольшого HTTP-сервиса в расширении — это стандарт де-факто, который сэкономит вам десятки часов отладки и обеспечит стабильную работу интеграции.