Как исправить ошибку «Файл не обнаружен» при создании WSОпределений из локального WSDL

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

Интеграция со сторонними сервисами по протоколу SOAP — частая задача в практике разработчика «1С:Предприятие 8». Традиционный подход с инициализацией веб-сервиса напрямую по сетевой ссылке через конструктор Новый WSОпределения("http://api.site.ru/service.wsdl") прост в реализации, но имеет существенные недостатки. Сетевые задержки, нестабильный интернет, падение удаленного сервера или блокировки могут сильно замедлить работу системы или вовсе заблокировать ключевые бизнес-процессы.

Для ускорения работы и повышения отказоустойчивости разработчики часто прибегают к логичному решению: сохраняют WSDL-описание во внутренний макет конфигурации (с типом «Двоичные данные»), а при необходимости инициализации выгружают его во временный файл на диск и передают путь к этому файлу в конструктор WSОпределения. Однако на этом этапе многие сталкиваются с загадочной ошибкой: платформа ругается на отсутствие файла, имя которого отличается от имени созданного временного файла. В этой статье мы подробно разберем, почему возникает эта проблема и как ее правильно решить несколькими способами.

Выясняем причину проблемы: механизм импорта в XML-схемах

Рассмотрим стандартную ситуацию. Разработчик выгружает двоичные данные из макета во временный файл с помощью метода ПолучитьИмяВременногоФайла("wsdl"). Платформа генерирует случайное уникальное имя в системном каталоге временных файлов, например: C:\Users\user\AppData\Local\Temp\v8_BF2A_2bb.wsdl. Файл успешно записывается на диск, но при попытке выполнить следующий код:

ОпределениеWS = Новый WSОпределения(ПутьКВременномуФайлу);

Платформа генерирует исключение:

«Ошибка при вызове конструктора (WSОпределения): При вызове веб-сервиса произошла ошибка. При создании описания сервиса произошла ошибка. : Файл не обнаружен 'C:\Users\user\AppData\Local\Temp\Service.wsdl'»

Проанализируем ситуацию: почему система ищет файл с именем Service.wsdl, если мы явно передали ей путь к файлу v8_BF2A_2bb.wsdl? Дело в том, что WSDL-документ — это сложная XML-структура, которая часто состоит не из одного файла, а собирается из нескольких связанных частей. Внутри основного файла WSDL почти всегда присутствуют директивы импорта внешних файлов или схем данных. Это могут быть теги следующего вида:

Когда платформа «1С:Предприятие 8» начинает парсить переданный ей файл v8_BF2A_2bb.wsdl, она натыкается на атрибут location (или schemaLocation) со значением "Service.wsdl". Поскольку этот путь является относительным, парсер пытается разрешить его относительно каталога, в котором находится базовый файл.

Базовый файл лежит в папке C:\Users\user\AppData\Local\Temp\, следовательно, 1С пытается найти импортируемый файл по пути C:\Users\user\AppData\Local\Temp\Service.wsdl. Так как на диске по этому пути ничего нет (ведь мы сохранили файл под случайным именем v8_BF2A_2bb.wsdl), платформа выдает закономерную ошибку о том, что файл не обнаружен.

---

Решение №1: Сохранение файла под его оригинальным (ожидаемым) именем

Самый простой и быстрый способ обойти данное ограничение — отказаться от генерации случайного имени файла через ПолучитьИмяВременногоФайла(). Вместо этого мы должны принудительно записать файл из макета в каталог временных файлов под тем именем, которое жестко прописано в теле WSDL-файла (в атрибуте location).

Выясним точное имя файла, открыв наш WSDL-файл в любом текстовом редакторе и найдя директиву location. Предположим, там указано Service.wsdl. Реализуем этот алгоритм на встроенном языке 1С:


// Получаем путь к системному каталогу временных файлов
КаталогВременныхФайлов = КаталогВременныхФайлов();

// Формируем точный путь с ожидаемым именем файла
ФайлWSDL = КаталогВременныхФайлов + "Service.wsdl"; 

// Получаем двоичные данные из макета конфигурации
ПолученныйМакет = ПолучитьМакет("service_wsdl");
ПолученныйМакет.Записать(ФайлWSDL);

Попытка
    // Инициализируем определения веб-сервиса из файла с корректным именем
    ОпределениеWS = Новый WSОпределения(ФайлWSDL);
Исключение
    ЗаписьЖурналаРегистрации("Интеграция.WS", УровеньЖурналаРегистрации.Ошибка,,, 
        "Ошибка создания WS-определений: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    ВызватьИсключение "Не удалось инициализировать веб-сервис. Обратитесь к администратору.";
КонецПопытки;

// После успешного создания объекта определения файл на диске больше не нужен
Попытка
    УдалитьФайлы(ФайлWSDL);
Исключение
    // Файл может быть кратковременно заблокирован процессом чтения, 
    // поэтому оборачиваем удаление в Попытка-Исключение
КонецПопытки;

Этот метод отлично работает, если WSDL-структура ссылается сама на себя или импортирует только один файл, имя которого нам заранее известно и неизменно.

---

Решение №2: Выгрузка связанных XSD-схем и зависимостей

В реальных интеграционных проектах (например, при обмене с государственными информационными системами или крупными ERP-системами) WSDL-файл часто импортирует целый каскад внешних файлов схем данных (файлы с расширением .xsd). Если вы перенесете в макет 1С только основной .wsdl, но забудете про сопутствующие .xsd, платформа выдаст аналогичную ошибку.

Рассмотрим по шагам, как правильно организовать работу со множественными зависимостями:

  1. Скачайте из исходного веб-сервиса сам WSDL-файл и все импортируемые им XSD-файлы.
  2. Добавьте каждый из этих файлов в конфигурацию 1С как отдельный макет с типом «Двоичные данные». Дайте макетам понятные имена (например: Макет_WSDL, Макет_XSD_Types, Макет_XSD_Core).
  3. В коде перед вызовом конструктора WSОпределения последовательно выгрузите все файлы в один и тот же временный каталог под их оригинальными именами.

Посмотрим на пример практической реализации такой выгрузки:


КаталогВременныхФайлов = КаталогВременныхФайлов();

// Структура, сопоставляющая имена макетов и целевые имена файлов на диске
СоответствиеФайлов = Новый Соответствие;
СоответствиеФайлов.Вставить("Макет_WSDL", "main.wsdl");
СоответствиеФайлов.Вставить("Макет_XSD_Types", "types.xsd");
СоответствиеФайлов.Вставить("Макет_XSD_Core", "core.xsd");

// Выгружаем все файлы в один каталог
Для Каждого Элемент Из СоответствиеФайлов Цикл
    Макет = ПолучитьМакет(Элемент.Ключ);
    ИмяФайлаНаДиске = КаталогВременныхФайлов + Элемент.Значение;
    Макет.Записать(ИмяФайлаНаДиске);
КонецЦикла;

// Инициализируем WSОпределения по главному файлу
ПутьКГлавномуФайлу = КаталогВременныхФайлов + "main.wsdl";
ОпределениеWS = Новый WSОпределения(ПутьКГлавномуФайлу);

// Производим зачистку всех временных файлов
Для Каждого Элемент Из СоответствиеФайлов Цикл
    ПутьКФайлу = КаталогВременныхФайлов + Элемент.Value;
    Попытка
        УдалитьФайлы(ПутьКФайлу);
    Исключение
        // Игнорируем ошибки блокировки файлов операционной системой
    КонецПопытки;
EndЦикла;

При таком подходе парсер платформы успешно найдет все необходимые схемы types.xsd и core.xsd в той же папке, где лежит main.wsdl, и построит корректную фабрику XDTO.

---

Решение №3: Объединение (Flattening) WSDL и XSD схем в один плоский файл

Если вам не хочется загромождать конфигурацию десятками макетов двоичных данных и писать сложную логику их одновременной выгрузки на диск, можно пойти по пути «слияния» всех зависимостей в один монолитный файл. Этот процесс в веб-разработке называется flattening (выравнивание).

Суть метода заключается в том, чтобы перенести все структуры данных из внешних файлов .xsd непосредственно внутрь самого WSDL-файла. Для этого:

Выполнить эту операцию можно вручную в любом продвинутом XML-редакторе (например, XMLSpy, Oxygen XML Editor) или воспользоваться бесплатными консольными утилитами для «выравнивания» WSDL. Полученный на выходе «плоский» WSDL-файл не будет иметь никаких внешних зависимостей. Его можно сохранять на диск под абсолютно любым случайным именем через ПолучитьИмяВременногоФайла() — он гарантированно прочитается платформой 1С без ошибок.

---

Решение №4: Динамическое редактирование WSDL-файла «на лету»

Иногда возникают ситуации, когда WSDL содержит ссылки на внешние интернет-ресурсы, доступ к которым у сервера «1С:Предприятие» ограничен настройками безопасности (например, закрыт доступ во внешнюю сеть файрволом). Если парсер 1С попытается разрешить внешние ссылки типа location="http://vendor-site.com/schemas/types.xsd", процесс завершится ошибкой таймаута.

В этом случае мы можем программно отредактировать текст WSDL перед тем, как отдавать его в конструктор WSОпределения. Проанализируем пример кода, который считывает WSDL как текст, удаляет или подменяет адреса внешних схем и записывает результат во временный файл:


// Считываем исходный текст WSDL-файла из макета
МакетWSDL = ПолучитьМакет("service_wsdl");
ИмяФайлаИсточника = ПолучитьИмяВременногоФайла("tmp");
МакетWSDL.Записать(ИмяФайлаИсточника);

ТекстWSDL = Новый ТекстовыйДокумент;
ТекстWSDL.Прочитать(ИмяФайлаИсточника);
СтроковыйТекст = ТекстWSDL.ПолучитьТекст();

// Производим замену внешних интернет-адресов схем на локальные файлы или относительные пути
// Например, если внешняя схема была скачана нами и лежит локально
СтроковыйТекст = СтрЗаменить(СтроковыйТекст, 
    "http://vendor-site.com/schemas/types.xsd", 
    "local_types.xsd");

// Записываем измененный текст в новый временный файл
ИмяФайлаДляЗагрузки = ПолучитьИмяВременногоФайла("wsdl");
ТекстWSDL.УстановитьТекст(СтроковыйТекст);
ТекстWSDL.Записать(ИмяФайлаДляЗагрузки);

// Выгружаем саму схему local_types.xsd, чтобы она была доступна парсеру в той же временной папке
КаталогВременныхФайлов = КаталогВременныхФайлов();
МакетСхемы = ПолучитьМакет("service_xsd");
МакетСхемы.Записать(КаталогВременныхФайлов + "local_types.xsd");

// Инициализируем WSОпределения
Попытка
    ОпределениеWS = Новый WSОпределения(ИмяФайлаДляЗагрузки);
Исключение
    ВызватьИсключение "Ошибка разбора измененного WSDL: " + ОписаниеОшибки();
КонецПопытки;

// Чистим временные файлы
УдалитьФайлы(ИмяФайлаИсточника);
УдалитьФайлы(ИмяФайлаДляЗагрузки);
УдалитьФайлы(КаталогВременныхФайлов + "local_types.xsd");

Этот гибкий подход позволяет динамически подстраивать конфигурацию под изменения сетевой инфраструктуры без необходимости полной переработки макетов.

---

Важные особенности платформы 1С при работе с локальными WSDL

Для того чтобы ваша интеграция работала стабильно, необходимо учитывать несколько критически важных особенностей платформы «1С:Предприятие 8» при работе с локальными XML-схемами:

Применяя описанные методики работы с локальными файлами определений, мы можем создавать быстрые, независимые от интернета и стабильные интеграционные решения на платформе «1С:Предприятие 8».

← На главную