Почему не работает поиск файлов при вызове через веб-сервис в 1С?

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

При разработке интеграций часто возникает ситуация, когда код, успешно работающий в обычной обработке или консоли запросов, начинает вести себя некорректно при вызове через Веб-сервис. Одной из самых распространенных проблем является "исчезновение" файлов: функция НайтиФайлы возвращает пустой массив или 0 объектов, хотя файлы гарантированно находятся в папке. Давайте подробно разберем, почему это происходит, и как правильно настроить окружение для корректной работы с файловой системой.

Разбираем причину: разница контекстов выполнения

Первое, что нам необходимо проанализировать — это контекст выполнения кода. Когда вы запускаете поиск файлов из обработки под своим пользователем, код выполняется в контексте вашего сеанса. Он видит все диски (включая сетевые Z:\, X:\) и имеет те же права на папки, что и ваш пользователь в Windows.

Однако, как только вызов идет через веб-сервис, ситуация кардинально меняется. Рассмотрим основные отличия:

  1. Серверный контекст: Веб-сервис всегда выполняется на стороне сервера. Это означает, что путь D:\ТестоваяПапка будет искаться на той физической машине, где установлен веб-сервер (IIS или Apache), а не на компьютере пользователя.
  2. Учетная запись службы: Веб-сервер работает под специфической системной учетной записью (например, IUSR, NetworkService или ApplicationPoolIdentity в IIS). У этой записи по умолчанию крайне ограниченные права в операционной системе.

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


Функция ПолучитьФайлыИзПапки(ПутьПоиска) Экспорт
    // Если ПутьПоиска = "D:\Files", сервер будет искать их у себя локально
    ИскомыеФайлы = НайтиФайлы(ПутьПоиска, "*.dbf");
    Возврат ИскомыеФайлы.Количество();
КонецФункции

Если веб-сервер и сервер 1С находятся на разных машинах, этот код гарантированно не найдет файлы, так как обращается к локальному диску "своей" машины.

Решение №1: Использование UNC-путей

Для того чтобы файлы были доступны из любого контекста, мы должны отказаться от использования букв дисков (C:\, D:\) в пользу сетевых путей формата UNC (Universal Naming Convention). Рассмотрим, как это выглядит на практике.

Вместо локального пути используем сетевое имя сервера:

\\ИмяСервера\ИмяРесурса\Папка\

Важно помнить, что сетевые диски, подключенные в вашей сессии Windows (например, диск Z:, указывающий на \\Server\Share), абсолютно невидимы для служб веб-сервера. Службы работают в так называемой "нулевой сессии", где нет никаких подключенных пользовательских дисков. Поэтому всегда прописывайте полный сетевой путь в коде или константах конфигурации.

Решение №2: Настройка прав доступа для службы веб-сервера

Даже если путь указан верно, функция НайтиФайлы вернет пустое значение, если у пользователя, от имени которого запущен веб-сервер, нет прав на чтение папки. Выясним, как это исправить по шагам:

  1. Определяем пользователя: Если вы используете IIS, откройте "Диспетчер служб IIS", перейдите в "Пулы приложений" и посмотрите, какая учетная запись указана в колонке "Удостоверение" (Identity) для вашего пула.
  2. Настраиваем безопасность папки: Нажмите правой кнопкой мыши на целевую папку -> Свойства -> Безопасность.
  3. Добавляем пользователя: Нажмите "Изменить" -> "Добавить" и введите имя пользователя (например, IIS_IUSRS или конкретную доменную учетную запись).
  4. Устанавливаем разрешения: Для корректной работы НайтиФайлы необходимы права "Чтение" и "Список содержимого папки".

Внимание: Если 1С-сервер и файлы находятся на разных машинах, "локальных" пользователей веб-сервера (типа IUSR) будет недостаточно. В этом случае необходимо запускать пул приложений IIS и службу "Агент сервера 1С:Предприятия" от имени доменной учетной записи, которая имеет доступ к сетевому хранилищу.

Решение №3: Передача данных через ДвоичныеДанные (Base64)

Если вы хотите избежать сложностей с настройкой прав доступа к файловой системе на сервере, рассмотрим более современный и безопасный архитектурный подход. Вместо того чтобы заставлять веб-сервис "ходить" за файлами, мы можем передавать содержимое файла напрямую в параметрах запроса.

Посмотрим на пример реализации передачи файла в веб-сервис:


// Код на стороне отправителя (клиента)
ПутьКФайлу = "D:\Data.dbf";
ДвоичныеДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);
// Передаем эти данные в веб-сервис как параметр типа base64Binary
Прокси.ЗагрузитьФайл(ДвоичныеДанныеФайла);

// Код на стороне веб-сервиса (сервера)
Функция ЗагрузитьФайл(ДанныеФайла)
    // Здесь ДанныеФайла уже имеют тип ДвоичныеДанные
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("dbf");
    ДанныеФайла.Записать(ИмяВременногоФайла);
    // Теперь мы можем работать с файлом локально на сервере
    // ... логика обработки ...
КонецФункции

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

Нюансы использования маски поиска

Проанализируем также маску поиска, которая упоминалась в обсуждении: "*.dbf*". Использование звездочки в конце расширения может привести к неожиданным результатам. Например, под такую маску попадут файлы data.dbf.bak или временные файлы report.dbf.tmp.

Рекомендуем использовать строгую маску, чтобы избежать ошибок при дальнейшей обработке объектов Файл:


// Более правильный вариант поиска
ИскомыеФайлы = НайтиФайлы(ПутьПоиска, "*.dbf", Ложь); 
// Ложь указывает на то, что поиск в подпапках не требуется

Резюме для стабильной работы

Чтобы ваш поиск файлов через веб-сервис работал безотказно, придерживайтесь следующих правил:

Применяя эти шаги, вы обеспечите надежную работу ваших интеграционных механизмов и избежите трудноуловимых ошибок, связанных с контекстом выполнения 1С.

← На главную