Как организовать копирование файлов в сетевой каталог в клиент-серверном варианте 1С?

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

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

Почему код перестает работать на сервере?

Прежде чем переходить к написанию кода, давайте проанализируем ситуацию и выясним основные причины возникновения ошибок в клиент-серверном режиме:

  1. Контекст выполнения. Когда вы вызываете процедуру с директивой &НаСервере, код исполняется на физическом сервере, где установлен «Агент сервера 1С:Предприятие». Переменные, содержащие пути вроде C:\MyFiles\photo.jpg, сервер будет искать на своих собственных локальных дисках, а не на компьютере пользователя.
  2. Права доступа службы. Служба 1С (обычно под пользователем USR1CV8) по умолчанию не имеет прав доступа к сетевым ресурсам (UNC-путям вида \\ServerName\Share). Даже если у текущего пользователя Windows есть доступ к папке, у сервера его может не быть.
  3. Интерактивные диалоги. На сервере невозможно вызвать ДиалогВыбораФайла, так как там нет графического интерфейса пользователя.

Решение №1. Копирование на стороне клиента

Самый простой и логичный способ, если пользователю доступны сетевые ресурсы — выполнить копирование прямо на клиенте. В этом случае 1С использует права текущего пользователя Windows, и нам не нужно настраивать доступ для системной службы сервера.

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


&НаКлиенте
Процедура ДобавитьФайлЭскиза(Команда)
    
    // 1. Выбираем файл на компьютере пользователя
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Выберите файл эскиза";
    Диалог.МножественныйВыбор = Ложь;
    
    Если Диалог.Выбрать() Тогда
        ПолныйПутьИсточник = Диалог.ПолноеИмяФайла;
        ИмяФайла = Диалог.ИмяФайла;
        
        // 2. Получаем необходимые данные с сервера (номер документа, имя покупателя)
        ДанныеДляПути = ПолучитьДанныеДляСозданияКаталога(Объект.Ссылка);
        
        // Формируем сетевой путь
        БазовыйКаталог = "\\192.168.0.249\эскизы\";
        ИмяПапки = ДанныеДляПути.ПокупательНаименование + " Заявка №" + ДанныеДляПути.Номер + " от " + Формат(ДанныеДляПути.Дата, "ДФ=dd.MM.yyyy");
        ЦелевойКаталог = БазовыйКаталог + ИмяПапки;
        ПолныйПутьНазначение = ЦелевойКаталог + "\" + ИмяФайла;
        
        // 3. Создаем каталог и копируем файл прямо на клиенте
        Попытка
            СоздатьКаталог(ЦелевойКаталог);
            КопироватьФайл(ПолныйПутьИсточник, ПолныйПутьНазначение);
            
            // 4. Записываем информацию в базу данных
            ДобавитьЗаписьВТЧНаСервере(ПолныйПутьНазначение, ИмяФайла);
            Сообщить("Файл успешно скопирован.");
        Исключение
            Сообщить("Ошибка при копировании файла: " + ОписаниеОшибки(), СтатусСообщения.Важное);
        КонецПопытки;
    КонецЕсли;

КонецПроцедуры

Обратите внимание, что функции СоздатьКаталог и КопироватьФайл доступны на клиенте в тонком клиенте Windows, что делает этот метод наиболее быстрым в реализации.

Решение №2. Передача файла через временное хранилище (Рекомендуемое)

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

Рассмотрим этот процесс по шагам:

  1. Пользователь выбирает файл на клиенте.
  2. Файл помещается во временное хранилище (бинарные данные улетают на сервер).
  3. На сервере мы извлекаем эти данные и записываем их в целевую папку.

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

&НаСервере
Процедура СохранитьФайлИзХранилищаНаСервере(АдресХранилища, ИмяФайла)
    
    // Формируем путь (сервер должен иметь доступ к этому UNC-пути!)
    ПутьКПапке = "\\1CSERVER\Files\Drawings\";
    СоздатьКаталог(ПутьКПапке);
    
    // Получаем данные из хранилища
    ДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    Если ТипЗнч(ДанныеФайла) = Тип("ДвоичныеДанные") Тогда
        ДанныеФайла.Записать(ПутьКПапке + ИмяФайла);
        
        // Добавляем строку в табличную часть
        НоваяСтрока = Объект.ТЧЭскизы.Добавить();
        НоваяСтрока.ПутьКФайлу = ПутьКПапке + ИмяФайла;
        // ... заполнение остальных реквизитов
    КонецЕсли;
    
КонецПроцедуры

Важные нюансы при работе с именами файлов

Проанализируем потенциальную проблему: в коде часто используется Объект.Покупатель.Наименование для создания папки. Это опасный момент. Если в наименовании контрагента встретятся символы /, \, *, :, ?, ", <, > или |, функция СоздатьКаталог вызовет исключение, так как эти символы запрещены в именах папок Windows.

Рекомендуем использовать вспомогательную функцию для «очистки» строки от недопустимых знаков:


Функция ОчиститьИмяФайла(Знач Имя) Экспорт
    ЗапрещенныеСимволы = "/\:*?""<>|";
    Для Индекс = 1 По СтрДлина(ЗапрещенныеСимволы) Цикл
        Символ = Сред(ЗапрещенныеСимволы, Индекс, 1);
        Имя = СтрЗаменить(Имя, Символ, "");
    КонецЦикла;
    Возврат СократЛП(Имя);
КонецФункции

Особенности настройки сервера 1С

Если вы решили сохранять файлы именно НаСервере, необходимо убедиться, что служба сервера имеет права на запись в сетевую папку. Рассмотрим, как это проверить:

Выясним еще один момент: если ваш сервер 1С работает под управлением Linux, то пути вида \\192.168.0.249\share работать не будут. В Linux сетевые папки нужно сначала смонтировать в файловую систему (например, в /mnt/drawings), и в коде 1С обращаться уже к этому локальному пути.

Заключение

Мы рассмотрели два основных подхода к копированию файлов. Выбор зависит от ваших требований к безопасности и прав доступа. Для простых задач идеально подходит выполнение НаКлиенте, так как это минимизирует нагрузку на сервер и упрощает работу с правами доступа. Для более сложных систем, где требуется централизованная обработка, используйте передачу через Временное хранилище. Всегда помните об обработке запрещенных символов в путях и проверяйте контекст выполнения кода (Клиент/Сервер), чтобы избежать ошибок «Файл не найден».

← На главную