Почему метод Существует() возвращает разные значения в тонком и веб-клиенте?

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

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

Анализ исходного кода и постановка задачи

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


Функция ПроверитьСуществованиеКаталога(ИмяКаталога) Экспорт
    КаталогНаДиске = Новый Файл(ИмяКаталога);
    Если КаталогНаДиске.Существует() Тогда  
        Возврат Истина;
    Иначе
        Возврат Ложь;   
    КонецЕсли; 
КонецФункции

На первый взгляд, код корректен. Однако при отладке выясняется, что в тонком клиенте КаталогНаДиске.Существует() возвращает Истина, а в веб-клиенте — Ложь. Чтобы понять, почему так происходит, нам нужно проанализировать, что именно 1С считает "сервером" в различных сценариях работы с файловой базой данных.

Различие контекстов исполнения: "Настоящий" и "Эмулируемый" сервер

Основная причина кроется в архитектуре файлового варианта работы 1С. Выясним, под чьим именем и в каком процессе выполняется код &НаСервере:

  1. Тонкий клиент (прямое подключение к файлу базы): В этом режиме серверный контекст создается ("эмулируется") прямо внутри процесса 1cv8c.exe на компьютере пользователя. Следовательно, код имеет доступ ко всем ресурсам, которые видит текущий пользователь Windows, запустивший 1С. Если у пользователя есть права на папку C:\Exchange, метод Существует() вернет Истина.
  2. Веб-клиент (через веб-сервер IIS или Apache): Здесь ситуация кардинально меняется. Клиент (браузер) взаимодействует с веб-сервером, который, в свою очередь, обращается к базе данных. Серверный код выполняется расширением веб-сервера (например, модулем w3wp.exe для IIS). Этот процесс запущен от имени специальной системной учетной записи (например, IUSR, IIS_IUSRS или NetworkService).

Таким образом, когда мы запускаем проверку из веб-клиента, метод Существует() выполняется от имени служебного пользователя веб-сервера. У этого пользователя по умолчанию нет прав доступа к большинству папок на диске, и уж тем более к сетевым шарам. Именно поэтому метод возвращает Ложь.

Как проверить контекст исполнения

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


#Если Сервер Тогда
    Сообщить("Это сервер");
#Иначе
    Сообщить("Упс, это клиент, это залет");
#КонецЕсли

Если в обоих случаях (тонкий и веб) вы видите сообщение "Это сервер", значит, проблема не в месте компиляции модуля, а именно в правах доступа операционной системы процесса, который этот сервер "олицетворяет".

Решение проблемы: Настройка прав доступа

Для того чтобы метод Существует() в веб-клиенте начал возвращать корректное значение, необходимо выполнить одно из следующих действий:

  1. Дать права пользователю веб-сервера: Нужно определить, под какой учетной записью работает ваш веб-сервер (IIS или Apache), и предоставить этой записи права на чтение (и запись, если требуется) для целевого каталога.
  2. Изменить пользователя службы: Вы можете настроить пул приложений IIS или службу Apache на запуск от имени конкретного доменного пользователя, у которого уже есть доступ ко всем необходимым ресурсам и сетевым путям.
  3. Использование сетевых путей (UNC): При работе через веб-сервер крайне важно использовать полные сетевые пути формата \\ServerName\Folder, а не локальные пути дисков типа D:\Data, так как диски могут быть не видны сервису.

Особенности асинхронной работы и современные стандарты

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


// Вместо громоздкого Если...Тогда...КонецЕсли
Результат = КаталогНаДиске.Существует();
Возврат Результат;

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

Влияние операционной системы сервера (Linux)

Рассмотрим ситуацию, когда ваш веб-сервер работает под управлением Linux (например, связка Apache + 1C на Ubuntu). В этом случае метод Существует() может возвращать Ложь еще по двум причинам:

Итоги и рекомендации

Подводя итог, можно сказать, что различие в поведении метода Существует() — это не ошибка платформы, а следствие работы механизмов безопасности операционной системы. Для стабильной работы рекомендуем:

← На главную