При интеграции сторонних систем с 1С через интерфейс OData разработчики часто сталкиваются с проблемой: запись в справочнике присоединенных файлов (например, СчетНаОплатуПокупателюПрисоединенныеФайлы) создается, но сам файл либо не открывается, либо вовсе не попадает в хранилище. Ситуация осложняется, если в настройках программы включено хранение файлов "В томах на диске". В этом случае обычный POST запрос не инициирует внутреннюю логику 1С по физическому перемещению данных на сервер. Разберем подробно, почему так происходит и как правильно реализовать загрузку.
Рассмотрим стандартную архитектуру 1С. Когда вы работаете через интерактивный интерфейс, подсистема «Работа с файлами» из состава Библиотеки стандартных подсистем (БСП) выполняет целый ряд действий:
СведенияОФайлах.Интерфейс OData работает на уровне платформы и выполняет прямую запись в таблицу базы данных. Он "не знает" о существовании модулей БСП и не вызывает процедуру ПрисоединенныеФайлы.ДобавитьФайл(). В итоге мы получаем запись, в которой прописан путь к файлу, но самого файла по этому адресу нет, либо у него не заполнены метаданные, из-за чего 1С выдает «Ошибку доступа к файлу».
Проанализируем самый простой и надежный способ без серьезной доработки конфигурации. Мы можем передать файл так, будто он должен храниться прямо в базе данных, а механизмы 1С сами переместят его на диск позже.
Для этого в POST запросе необходимо изменить параметры хранения. Рассмотрим пример структуры JSON для такого запроса:
{
"Description": "Имя_Файла.pdf",
"Расширение": "pdf",
"ВладелецФайла_Key": "8ab01ee2-151e-11eb-80f2-0050569a8809",
"ТипХраненияФайла": "ВИнформационнойБазе",
"Размер": 12345,
"ФайлХранилище_Base64Data": "JVBERi0xLjQKJ...[длинная строка base64]..."
}
Важные моменты этого способа:
ТипХраненияФайла со значением ВИнформационнойБазе. Это заставит платформу сохранить данные в реквизит ФайлХранилище.Размер файла. Без него логика БСП может посчитать файл поврежденным.ТипХраненияФайла на ВТомахНаДиске.Если нам нужно, чтобы файл попадал в том мгновенно, или мы не хотим забивать базу временным хранением, можно внести изменения в модуль справочника ...ПрисоединенныеФайлы. Выясним, как программно заставить 1С обработать данные из OData.
В модуле объекта в процедуре ПриЗаписи пропишем логику, которая будет срабатывать только при загрузке через веб-сервис. Для этого удобно использовать ДополнительныеСвойства или проверку на установку обмена данными.
Процедура ПриЗаписи(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем, что файл пришел через OData и данные находятся в реквизите ФайлХранилище
Если ЗначениеЗаполнено(ЭтотОбъект.ФайлХранилище)
И ЭтотОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
// Вызываем логику БСП для перемещения в том
ПараметрыФайла = Новый Структура("ИмяБезРасширения, Расширение", ЭтотОбъект.Наименование, ЭтотОбъект.Расширение);
ДанныеФайла = ЭтотОбъект.ФайлХранилище.Получить();
// ВНИМАНИЕ: Здесь нужно использовать методы БСП для корректного заполнения тома
// Например, РаботаСФайлами.ПоложитьФайлВХранилище(...)
КонецЕсли;
КонецПроцедуры
Примечание: Этот метод требует осторожности, так как ПриЗаписи вызывается часто, и лишние проверки не должны замедлять работу системы.
Разберем ситуацию, когда OData становится слишком сложным инструментом для простой задачи. Профессиональным подходом считается создание небольшого HTTP-сервиса в 1С специально для приема файлов. Это решает сразу все проблемы:
ПрисоединенныеФайлы.ДобавитьФайл().Пример фрагмента кода в HTTP-сервисе:
Функция ДобавитьФайл(Запрос)
Данные = Запрос.ПолучитьТелоКакДвоичныеДанные();
ВладелецСсылка = Справочники.СчетаНаОплатуПокупателю.ПолучитьСсылку(Новый УникальныйИдентификатор(GUID));
ПараметрыФайла = Новый Структура;
ПараметрыФайла.Вставить("Автор", Пользователи.ТекущийПользователь());
ПараметрыФайла.Вставить("ИмяФайла", "contract.pdf");
Результат = ПрисоединенныеФайлы.ДобавитьФайл(ВладелецСсылка, "Договор", , ПараметрыФайла, Данные);
Возврат Новый HTTPСервисОтвет(201);
КонецФункции
Проанализируем типичные ошибки, о которых упоминалось в обсуждении:
USR1CV8). Именно у этого пользователя Windows должны быть права "Полный доступ" на сетевой каталог или локальную папку, где расположены тома.Content-Type: application/json. Поле ФайлХранилище_Type часто может принимать значение application/octet-stream для двоичных данных.maxAllowedContentLength).Подводя итог: если вы ограничены использованием исключительно OData, используйте Способ №1 (загрузка в базу с типом "ВИнформационнойБазе"). Это позволит избежать конфликтов с логикой БСП и обеспечит сохранность файлов с их последующим автоматическим переносом на дисковые тома штатными средствами 1С.