В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда один и тот же код, написанный для исполнения на сервере, выдает разные результаты в зависимости от типа используемого клиента (тонкий клиент или веб-клиент). Особенно ярко это проявляется при работе с файловой системой. Разберем типичную ситуацию: функция проверки существования каталога, вызванная &НаСервере, возвращает Истина в тонком клиенте и Ложь в веб-клиенте.
Рассмотрим стандартную функцию, которая располагается в общем модуле с установленными флагами Сервер и Вызов сервера. Программист ожидает, что раз код выполняется на сервере, то и результат поиска файла на диске сервера должен быть идентичным для всех подключений. Типовой пример кода выглядит следующим образом:
Функция ПроверитьСуществованиеКаталога(ИмяКаталога) Экспорт
КаталогНаДиске = Новый Файл(ИмяКаталога);
Если КаталогНаДиске.Существует() Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
На первый взгляд, код корректен. Однако при отладке выясняется, что в тонком клиенте КаталогНаДиске.Существует() возвращает Истина, а в веб-клиенте — Ложь. Чтобы понять, почему так происходит, нам нужно проанализировать, что именно 1С считает "сервером" в различных сценариях работы с файловой базой данных.
Основная причина кроется в архитектуре файлового варианта работы 1С. Выясним, под чьим именем и в каком процессе выполняется код &НаСервере:
1cv8c.exe на компьютере пользователя. Следовательно, код имеет доступ ко всем ресурсам, которые видит текущий пользователь Windows, запустивший 1С. Если у пользователя есть права на папку C:\Exchange, метод Существует() вернет Истина.w3wp.exe для IIS). Этот процесс запущен от имени специальной системной учетной записи (например, IUSR, IIS_IUSRS или NetworkService).Таким образом, когда мы запускаем проверку из веб-клиента, метод Существует() выполняется от имени служебного пользователя веб-сервера. У этого пользователя по умолчанию нет прав доступа к большинству папок на диске, и уж тем более к сетевым шарам. Именно поэтому метод возвращает Ложь.
Для диагностики того, действительно ли код выполняется на сервере, можно воспользоваться инструкциями препроцессора. Рассмотрим, как это сделать правильно, чтобы исключить влияние клиентского контекста:
#Если Сервер Тогда
Сообщить("Это сервер");
#Иначе
Сообщить("Упс, это клиент, это залет");
#КонецЕсли
Если в обоих случаях (тонкий и веб) вы видите сообщение "Это сервер", значит, проблема не в месте компиляции модуля, а именно в правах доступа операционной системы процесса, который этот сервер "олицетворяет".
Для того чтобы метод Существует() в веб-клиенте начал возвращать корректное значение, необходимо выполнить одно из следующих действий:
\\ServerName\Folder, а не локальные пути дисков типа D:\Data, так как диски могут быть не видны сервису.Проанализируем еще один важный аспект. В современных версиях платформы (особенно если конфигурация готовится к работе в облаке 1С:Фреш) использование синхронных методов объекта Файл на стороне клиента запрещено или ограничено. Хотя в нашем примере код серверный, стоит помнить о правильном подходе к написанию подобных функций для обеспечения чистоты кода:
// Вместо громоздкого Если...Тогда...КонецЕсли
Результат = КаталогНаДиске.Существует();
Возврат Результат;
Если бы проверка происходила на стороне клиента (например, в мобильном приложении или для интерактивного выбора файла), следовало бы использовать асинхронный метод НачатьПроверкуСуществования(). Веб-клиенты особенно чувствительны к синхронным вызовам, так как они могут "подвешивать" интерфейс браузера.
Рассмотрим ситуацию, когда ваш веб-сервер работает под управлением Linux (например, связка Apache + 1C на Ubuntu). В этом случае метод Существует() может возвращать Ложь еще по двум причинам:
/home/user/Data и /home/user/data — это разные объекты. Если путь в переменной ИмяКаталога не совпадает по регистру с реальной папкой на диске, 1С ее не найдет.\, а в Linux — прямой /. Проанализируйте способ формирования пути. Универсальным решением будет использование функции ПолучитьРазделительПути().Подводя итог, можно сказать, что различие в поведении метода Существует() — это не ошибка платформы, а следствие работы механизмов безопасности операционной системы. Для стабильной работы рекомендуем: