При разработке в среде 1С:Предприятие, особенно в режиме Обычного приложения, программисты часто сталкиваются с ситуацией, когда код прекрасно работает при запуске базы на самом сервере (через RDP), но отказывается функционировать при подключении с клиентского компьютера. Типичный пример: проверка существования файла по локальному пути типа D:\Files\data.mxl. Разберем подробно, почему так происходит и как правильно организовать проверку и чтение серверных файлов.
Проанализируем ситуацию: если вы запускаете базу на сервере, ваш сеанс (клиентская часть) и файлы находятся на одном и том же физическом диске. В этом случае 1С видит путь D:\1sb8\.... Однако, когда вы подключаетесь с другого компьютера, код проверки файла по умолчанию выполняется на клиенте. Клиентское приложение ищет диск D: на локальной машине пользователя, а не на сервере, и, естественно, ничего не находит.
Многие полагают, что установка галочки "Сервер" в свойствах общего модуля автоматически заставляет код работать на сервере. В управляемых формах это регулируется директивами &НаСервере, но в обычных формах ситуация иная. Если у модуля стоят флаги "Клиент" и "Сервер", то при вызове из обычной формы приоритет отдается клиентскому исполнению. Рассмотрим, как гарантировать выполнение кода именно на стороне сервера.
Прежде чем приступать к написанию кода, важно выяснить одну критическую деталь: под чьим именем работает сервер 1С. Выясним причину, по которой даже "правильный" серверный код может не видеть файл. Когда код выполняется на сервере, он обращается к операционной системе от имени пользователя, под которым запущена служба "Агент сервера 1С:Предприятия" (обычно это USR1CV8).
Что необходимо проверить:
USR1CV8) есть права на чтение и просмотр содержимого папки D:\1sb8\Коды_ТНВЭД\. Если файл лежит в профиле другого пользователя или на закрытом системном диске, служба его не увидит, даже если он там есть.Рассмотрим сценарий, когда нам нужно не просто проверить наличие файла, но и прочитать его содержимое (например, табличный документ) на сервере, а затем отобразить результат пользователю на клиенте. Для этого лучше всего подходит механизм Временного хранилища.
Посмотрим на пример правильной реализации функций в общем модуле, который имеет флаг "Сервер" (и желательно только его, либо вызывается из строго серверного контекста):
// Функция выполняется строго на сервере
Функция ПолучитьАдресФайлаНаСервере() Экспорт
ПутьКФайлу = "D:\1sb8\Коды_ТНВЭД\Список ГСВС.mxl";
ФайлНаДиске = Новый Файл(ПутьКФайлу);
Если НЕ ФайлНаДиске.Существует() Тогда
Возврат Неопределено;
КонецЕсли;
// Читаем табличный документ на сервере
ТабДок = Новый ТабличныйДокумент;
Попытка
ТабДок.Прочитать(ПутьКФайлу);
Исключение
Сообщить("Ошибка чтения файла: " + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
// Помещаем объект во временное хранилище и возвращаем адрес
Возврат ПоместитьВоВременноеХранилище(ТабДок);
КонецФункции
На стороне клиента (в форме или клиентском модуле) мы вызываем эту функцию и получаем объект обратно:
Процедура ЗагрузитьДанныеССервера()
Адрес = ОбщийМодульСервер.ПолучитьАдресФайлаНаСервере();
Если Адрес = Неопределено Тогда
Предупреждение("Файл на сервере не найден!");
Возврат;
КонецЕсли;
// Получаем объект из хранилища
РезультатТабДок = ПолучитьИзВременногоХранилища(Адрес);
// Теперь РезультатТабДок доступен на клиенте
КонецПроцедуры
Важный нюанс: Не используйте устаревшие функции ЗначениеВСТрокуВнутр для передачи сложных объектов вроде ТабличныйДокумент. Метод ПоместитьВоВременноеХранилище прекрасно справляется с передачей объектов напрямую.
Иногда объект Новый Файл() может вести себя некорректно при специфических настройках прав. Проанализируем альтернативный способ проверки через функцию НайтиФайлы(). Этот метод возвращает массив найденных объектов, и если он пуст — файла не существует.
Функция ФайлСуществуетНаСервере(ПолныйПуть) Экспорт
МассивФайлов = НайтиФайлы(ПолныйПуть);
Возврат МассивФайлов.Количество() > 0;
КонецФункции
Этот метод удобен тем, что поддерживает маски (например, *.mxl), что позволяет делать более гибкие проверки.
Разберем ситуацию: если ваш файл Список ГСВС.mxl является справочным и меняется не каждый час, то хранить его просто "на диске D:" — не самая лучшая практика. Это создает зависимость от файловой системы и конкретного сервера. В кластере 1С может быть несколько рабочих серверов, и файл должен лежать на каждом из них по одному и тому же пути.
Рекомендуемый подход:
ЭтотОбъект.ПолучитьМакет("ИмяМакета").В этом случае данные будут храниться внутри базы данных, они будут доступны мгновенно на любом сервере кластера и любому пользователю, независимо от его прав на папки Windows.
Для успешной проверки файла на сервере необходимо:
USR1CV8 к целевой директории.ПоместитьВоВременноеХранилище / ПолучитьИзВременногоХранилища.