Интеграция между конфигурациями «1С:Бухгалтерия» (БП) и «1С:Документооборот» (ДО) — распространенная задача. Часто возникает потребность не просто видеть карточку документа, но и программно скачивать прикрепленные файлы (например, сканы договоров или счетов) для сохранения их локально или обработки на стороне бухгалтерской системы. В некоторых случаях может потребоваться полная выгрузка данных в автономное дерево HTML для ознакомления с архивом вне системы 1С.
В этой статье мы подробно разберем, как получить данные из справочника Файлы и само содержимое файла (двоичные данные), используя стандартные механизмы веб-сервисов (DMService), а также рассмотрим альтернативный подход с созданием собственного HTTP-сервиса.
Основной способ взаимодействия с 1С:Документооборот — использование SOAP веб-сервиса DMService. Этот метод является стандартным для большинства типовых интеграций.
При использовании простых запросов типа DMGetObjectListRequest, мы часто получаем только базовые поля (имя, ID), но не видим расширения, автора или самого контента файла. Чтобы получить детальную информацию и двоичные данные, необходимо правильно настроить список запрашиваемых колонок — columnSet.
Для начала нам понадобится прокси-объект интеграции. В типовых конфигурациях (БП, ERP) часто есть общие модули для работы с ДО. Рассмотрим функцию, которая запрашивает файлы конкретного документа:
// Функция возвращает список файлов (XDTO) по объекту-владельцу из ДО
Функция ФайлыПоВладельцу(ИдентификаторВладельца, ИмяВладельца, ТипВладельца, ВключатьПомеченныеНаУдаление = Ложь) Экспорт
// Получаем прокси (предполагается, что настройки соединения уже заданы в базе)
Прокси = ИнтеграцияС1СДокументооборотБазоваяФункциональностьПовтИсп.ПолучитьПрокси();
// Создаем запрос специального типа DMGetFileListByOwnerRequest
Запрос = ИнтеграцияС1СДокументооборотБазоваяФункциональность.СоздатьОбъект(Прокси, "DMGetFileListByOwnerRequest");
ПолучаемыеПоля = Запрос.columnSet; // Сюда мы добавим нужные нам поля
Владельцы = Запрос.owners;
// Формируем объект-владельца (например, Внутренний документ)
ОбъектВладелец = ИнтеграцияС1СДокументооборотБазоваяФункциональность.СоздатьОбъект(Прокси, "DMObject");
ОбъектВладелец.name = ИмяВладельца;
ОбъектВладелец.objectID = ИнтеграцияС1СДокументооборотБазоваяФункциональность.СоздатьObjectID(
Прокси,
Строка(ИдентификаторВладельца),
ТипВладельца);
Владельцы.Добавить(ОбъектВладелец);
// Явно указываем, какие поля хотим вернуть
ПолучаемыеПоля.Добавить("objectID");
ПолучаемыеПоля.Добавить("name"); // Имя файла
ПолучаемыеПоля.Добавить("size"); // Размер
ПолучаемыеПоля.Добавить("extension"); // Расширение
ПолучаемыеПоля.Добавить("modificationDateUniversal");
// Самое важное: запрашиваем двоичные данные файла
ПолучаемыеПоля.Добавить("binaryData");
Если ВключатьПомеченныеНаУдаление Тогда
Запрос.ignoreDeletionMark = Истина;
ПолучаемыеПоля.Добавить("deletionMark");
КонецЕсли;
// Выполняем запрос к веб-сервису
Файлы = ИнтеграцияС1СДокументооборотБазоваяФункциональность.ВыполнитьЗапрос(Прокси, Запрос);
// Проверяем на ошибки
ИнтеграцияС1СДокументооборотБазоваяФункциональность.ПроверитьВозвратВебСервиса(Прокси, Файлы);
Возврат Файлы;
КонецФункции
Важные нюансы данного метода:
DMGetFileListByOwnerRequest, а не общий DMGetObjectListRequest, если вам нужны именно файлы, привязанные к документу.columnSet. Если вы попытаетесь обратиться к полям, которые не добавили в columnSet, они будут пустыми.Иногда штатный механизм слишком громоздок или медленен. Например, если файлы попадают в систему через обработчик бизнес-события поступления почты и вам нужна сложная логика выборки по ИНН контрагента. В этом случае на стороне ДО создается свой HTTP-сервис.
Рассмотрим пример реализации метода GET, который принимает ИНН и возвращает JSON со списком файлов.
Код HTTP-сервиса на стороне ДО:
Функция ПолучитьФайлыGET(Запрос)
Попытка
Ответ = Новый HTTPСервисОтвет(200);
ИНН = Запрос.ПараметрыURL["inn"]; // Читаем параметр из URL
// Получаем JSON строку с данными
СтрокаJSON = ПолучитьФайлыПоИНН(ИНН);
Ответ.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.Использовать);
Исключение
Ответ = Новый HTTPСервисОтвет(404);
ТекстСообщения = СтрШаблон(НСтр("ru = 'Ошибка метода: %1'"), ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Ответ.УстановитьТелоИзСтроки(ТекстСообщения);
КонецПопытки;
Возврат Ответ;
КонецФункции
Вспомогательная функция ПолучитьФайлыПоИНН выполняет запрос к базе данных ДО, обращаясь к таблицам Справочник.ВнутренниеДокументы и Справочник.Файлы.
Функция ПолучитьФайлыПоИНН(ИНН)
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ИНН", ИНН);
// Упрощенный пример запроса
Запрос.Текст =
"ВЫБРАТЬ
| Файлы.Наименование КАК НаименованиеФайла,
| Файлы.ТекущаяВерсияРасширение КАК Расширение,
| Файлы.ТекущаяВерсияПутьКФайлу КАК ПутьКФайлуВТоме,
| ЕСТЬNULL(Файлы.ТекущаяВерсияТом.ПолныйПутьWindows, """") КАК ПутьКТому
|ИЗ
| Справочник.ВнутренниеДокументы КАК ВнутренниеДокументы
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Файлы КАК Файлы
| ПО ВнутренниеДокументы.Ссылка = Файлы.ВладелецФайла
|ГДЕ
| ВнутренниеДокументы.Контрагент.ИНН = &ИНН
| И НЕ Файлы.ПометкаУдаления";
// ... выполнение запроса и формирование массива структур ...
// Сериализация в JSON
НастройкиJSON = Новый НастройкиСериализацииJSON;
НастройкиJSON.ВариантЗаписиДаты = ВариантЗаписиДатыJSON.ЛокальнаяДата;
Возврат СериализоватьJSON(МассивРезультатов, НастройкиJSON);
КонецФункции
Преимущества этого подхода:
binaryData для списка из 100 файлов. Лучше сначала получить список ID и имен, а затем скачивать контент только для выбранного файла.Файлы (карточка) и ВерсииФайлов. Двоичные данные хранятся именно в версиях. При использовании запросов 1С обращайтесь к реквизитам ТекущаяВерсия....