Как решить проблему "Файл не обнаружен" при выполнении фонового задания на сервере 1С?

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

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

Анализ проблемы: почему локальные пути не работают?

Рассмотрим типичную ситуацию. В коде прописан путь к файлу в формате E:\project\contr.xml. Когда вы запускаете этот код со своего рабочего места (в толстом или тонком клиенте), операционная система понимает, что диск E: — это ваш локальный или подключенный сетевой диск. Однако, как только управление передается фоновому заданию на сервер, контекст исполнения кардинально меняется.

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

  1. Изоляция сессий (Session 0): Служба сервера 1С:Предприятие работает в так называемой «нулевой сессии». В этой сессии не монтируются сетевые диски, которые вы видите в своем проводнике под буквами Z:, X: или E:. Даже если диск E: физически находится на сервере, права доступа к нему для службы могут быть ограничены.
  2. Учетная запись службы: По умолчанию сервер 1С часто устанавливается от имени системной учетной записи LocalSystem (Локальная система). Эта учетная запись обладает огромными правами внутри локального компьютера, но практически «анонимна» для сетевых ресурсов.
  3. Виртуализация путей: Если диск E: является «мэппированным» (Mapped Drive) сетевым ресурсом, он существует только в рамках сеанса конкретного пользователя. Для серверной службы такого диска просто не существует.

Переход к UNC-путям — правильное решение

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

Вместо обращения E:\project\contr.xml следует использовать путь вида: \\ИмяСервера\ИмяПапки\contr.xml. Это позволяет службе сервера 1С обращаться к ресурсу напрямую через сетевой протокол, минуя механизмы монтирования дисков в пользовательской сессии.

Проанализируем исправленный фрагмент кода, который решает проблему доступа:


// Правильный подход с использованием UNC-пути
ПутьКФайлу = "\\server-dc\project\contr.xml"; 

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

Настройка прав доступа для службы 1С

Даже если вы прописали UNC-путь, файл может остаться недоступным из-за ограничений прав. Выясним, как правильно настроить доступ:

Если служба 1С (1C:Enterprise 8.3 Server Agent) запущена от имени LocalSystem, то для доступа к сетевой папке на другом сервере вам придется давать права на эту папку учетной записи самого компьютера, на котором стоит 1С (формат ДОМЕН\ИМЯ_СЕРВЕРА$). Это не всегда удобно и безопасно.

Рекомендуемый алгоритм настройки:

  1. Создайте в домене специального пользователя, например usr_1c_service.
  2. Настройте запуск службы сервера 1С от имени этого пользователя.
  3. В настройках безопасности сетевой папки (вкладки "Sharing" и "Security") добавьте этого пользователя и предоставьте ему права на чтение (и запись, если требуется).
  4. Перезапустите службу сервера 1С.

Работа через Временное хранилище и двоичные данные

Иногда требуется передать файл с клиента на сервер для последующей обработки в фоновом задании. В этом случае мы используем ПоместитьВоВременноеХранилище. Посмотрим на этот процесс подробнее, так как здесь тоже есть свои нюансы.

Рассмотрим ситуацию: пользователь выбирает файл на своем компьютере, а фоновое задание должно его обработать. Напрямую фоновое задание не сможет достучаться до файла на диске C: пользователя. Нам нужно передать данные через хранилище.

Шаг 1: Помещение файла в хранилище (на клиенте)


// Код на клиенте
ДанныеФайла = Новый ДвоичныеДанные(ПутьВыбранныйПользователем);
АдресХранилища = ПоместитьВоВременноеХранилище(ДанныеФайла, УникальныйИдентификатор);
// Теперь передаем АдресХранилища в фоновое задание как параметр

Шаг 2: Получение и сохранение файла (на сервере в фоновом задании)

Важно помнить, что методы чтения файлов (например, ЧтениеXML или ЧтениеТекста) работают с файлами на диске, а не с объектами в памяти. Поэтому нам нужно сохранить двоичные данные во временный файл на стороне сервера.


// Код внутри серверной процедуры фонового задания
Данные = ПолучитьИзВременногоХранилища(ПараметрАдрес);
Если Данные <> Неопределено Тогда
    // Создаем имя временного файла в серверной папке Temp
    ПутьКВременномуФайлу = ПолучитьИмяВременногоФайла("xml");
    
    // Записываем данные на диск сервера
    Данные.Записать(ПутьКВременномуФайлу);
    
    // Работаем с файлом
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.ОткрытьФайл(ПутьКВременномуФайлу);
    
    // ... логика обработки XDTO или Чтения XML ...
    
    ЧтениеXML.Закрыть();
    
    // Обязательно удаляем за собой временный файл
    Попытка
        УдалитьФайлы(ПутьКВременномуФайлу);
    Исключение
        // Логируем, если файл занят
    КонецПопытки;
КонецЕсли;

Оптимизация чтения больших XML-файлов

В приведенных примерах часто используется метод ФабрикаXDTO.ПрочитатьXML(). Проанализируем этот подход. Метод крайне удобен, так как превращает XML в дерево объектов, с которыми легко работать через точку (например, Элемент.Наименование).

Однако помните о рисках:

Если ваш XML-файл весит несколько сотен мегабайт, метод ПрочитатьXML попытается загрузить его целиком в оперативную память сервера. Это может привести к падению рабочего процесса 1С с ошибкой нехватки памяти (Out of memory). Для работы с действительно большими файлами используйте последовательное чтение:


Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлу);
Пока Чтение.Прочитать() Цикл
    Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "ЭлементСправочника" Тогда
        // Читаем по одному объекту, не загружая весь файл
        ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(Чтение, ФабрикаXDTO.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogObject.ДисконтКарты"));
        // Обработка конкретной карты...
    КонецЕсли;
КонецЦикла;
Чтение.Закрыть();

Резюме и рекомендации

Для стабильной работы фоновых заданий с файлами придерживайтесь следующих правил:

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

← На главную