Как загрузить присоединенные файлы в 1С через OData, если используется хранение в томах на диске?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции сторонних систем с 1С через интерфейс OData разработчики часто сталкиваются с проблемой: запись в справочнике присоединенных файлов (например, СчетНаОплатуПокупателюПрисоединенныеФайлы) создается, но сам файл либо не открывается, либо вовсе не попадает в хранилище. Ситуация осложняется, если в настройках программы включено хранение файлов "В томах на диске". В этом случае обычный POST запрос не инициирует внутреннюю логику 1С по физическому перемещению данных на сервер. Разберем подробно, почему так происходит и как правильно реализовать загрузку.

Проблема: Почему стандартный POST запрос не работает для томов?

Рассмотрим стандартную архитектуру 1С. Когда вы работаете через интерактивный интерфейс, подсистема «Работа с файлами» из состава Библиотеки стандартных подсистем (БСП) выполняет целый ряд действий:

  1. Создает запись в справочнике файлов.
  2. Вычисляет контрольную сумму (MD5) и размер файла.
  3. Определяет текущий активный том на диске.
  4. Перемещает двоичные данные в папку на сервере, создавая структуру подпапок (например, по датам).
  5. Заполняет служебные сведения в регистре СведенияОФайлах.

Интерфейс OData работает на уровне платформы и выполняет прямую запись в таблицу базы данных. Он "не знает" о существовании модулей БСП и не вызывает процедуру ПрисоединенныеФайлы.ДобавитьФайл(). В итоге мы получаем запись, в которой прописан путь к файлу, но самого файла по этому адресу нет, либо у него не заполнены метаданные, из-за чего 1С выдает «Ошибку доступа к файлу».

Способ №1: Загрузка через информационную базу с последующим переносом

Проанализируем самый простой и надежный способ без серьезной доработки конфигурации. Мы можем передать файл так, будто он должен храниться прямо в базе данных, а механизмы 1С сами переместят его на диск позже.

Для этого в POST запросе необходимо изменить параметры хранения. Рассмотрим пример структуры JSON для такого запроса:


{
"Description": "Имя_Файла.pdf",
"Расширение": "pdf",
"ВладелецФайла_Key": "8ab01ee2-151e-11eb-80f2-0050569a8809",
"ТипХраненияФайла": "ВИнформационнойБазе",
"Размер": 12345,
"ФайлХранилище_Base64Data": "JVBERi0xLjQKJ...[длинная строка base64]..."
}

Важные моменты этого способа:

Способ №2: Доработка модуля объекта (перехват записи)

Если нам нужно, чтобы файл попадал в том мгновенно, или мы не хотим забивать базу временным хранением, можно внести изменения в модуль справочника ...ПрисоединенныеФайлы. Выясним, как программно заставить 1С обработать данные из OData.

В модуле объекта в процедуре ПриЗаписи пропишем логику, которая будет срабатывать только при загрузке через веб-сервис. Для этого удобно использовать ДополнительныеСвойства или проверку на установку обмена данными.


Процедура ПриЗаписи(Отказ)
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Проверяем, что файл пришел через OData и данные находятся в реквизите ФайлХранилище
    Если ЗначениеЗаполнено(ЭтотОбъект.ФайлХранилище) 
         И ЭтотОбъект.ТипХраненияФайла = Перечисления.ТипыХраненияФайлов.ВТомахНаДиске Тогда
        
        // Вызываем логику БСП для перемещения в том
        ПараметрыФайла = Новый Структура("ИмяБезРасширения, Расширение", ЭтотОбъект.Наименование, ЭтотОбъект.Расширение);
        ДанныеФайла = ЭтотОбъект.ФайлХранилище.Получить();
        
        // ВНИМАНИЕ: Здесь нужно использовать методы БСП для корректного заполнения тома
        // Например, РаботаСФайлами.ПоложитьФайлВХранилище(...)
    КонецЕсли;
КонецПроцедуры

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

Способ №3: Использование собственного HTTP-сервиса (Best Practice)

Разберем ситуацию, когда OData становится слишком сложным инструментом для простой задачи. Профессиональным подходом считается создание небольшого HTTP-сервиса в 1С специально для приема файлов. Это решает сразу все проблемы:

  1. Вы можете передать файл в теле запроса (Binary), не кодируя его в Base64 (что экономит до 30% трафика и памяти).
  2. В коде сервиса вы вызываете штатную функцию БСП: ПрисоединенныеФайлы.ДобавитьФайл().
  3. Функция сама создаст запись в справочнике, заполнит все регистры, рассчитает MD5 и положит файл в правильную папку на диске.

Пример фрагмента кода в HTTP-сервисе:


Функция ДобавитьФайл(Запрос)
    Данные = Запрос.ПолучитьТелоКакДвоичныеДанные();
    ВладелецСсылка = Справочники.СчетаНаОплатуПокупателю.ПолучитьСсылку(Новый УникальныйИдентификатор(GUID));
    
    ПараметрыФайла = Новый Структура;
    ПараметрыФайла.Вставить("Автор", Пользователи.ТекущийПользователь());
    ПараметрыФайла.Вставить("ИмяФайла", "contract.pdf");
    
    Результат = ПрисоединенныеФайлы.ДобавитьФайл(ВладелецСсылка, "Договор", , ПараметрыФайла, Данные);
    Возврат Новый HTTPСервисОтвет(201);
КонецФункции

Нюансы с правами доступа и форматами

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

Подводя итог: если вы ограничены использованием исключительно OData, используйте Способ №1 (загрузка в базу с типом "ВИнформационнойБазе"). Это позволит избежать конфликтов с логикой БСП и обеспечит сохранность файлов с их последующим автоматическим переносом на дисковые тома штатными средствами 1С.

← На главную