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

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

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

Понимание контекста: Клиент и Сервер в толстом клиенте

Для начала проанализируем ситуацию. В обычном приложении 1С код модуля формы по умолчанию выполняется на стороне клиента. В отличие от управляемого приложения, здесь нет явных директив &НаСервере или &НаКлиенте. Чтобы код действительно выполнился на стороне сервера (что критично для записи файла в серверную папку), нам необходимо использовать специальные механизмы платформы.

Многие начинающие разработчики полагают, что в толстом клиенте "сервер" находится там же, где и "клиент". Это верно только для файловых баз. В клиент-серверном варианте (SQL) физический сервер приложений может находиться на другом компьютере, и прямой доступ к его диску через обычный путь C:\Temp с клиента невозможен.

Метод 1: Использование временного хранилища и ПоместитьФайл()

Это наиболее "правильный" с точки зрения платформы способ, который работает в версиях 8.2 и 8.3. Мы используем временное хранилище как промежуточный буфер.

Рассмотрим пошагово, как это реализовать:

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

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


Процедура КнопкаЗагрузитьНажатие(Элемент)
    Перем ВыбранныйПуть;
    АдресХранилища = "";
    
    // В обычных формах метод ПоместитьФайл работает синхронно
    // Важно передать УникальныйИдентификатор формы, чтобы данные не удалились сразу
    Если ПоместитьФайл(АдресХранилища, "", ВыбранныйПуть, Истина, ЭтаФорма.УникальныйИдентификатор) Тогда
        // Теперь вызываем серверный метод для сохранения
        РаботаСФайламиСервер.СохранитьФайлИзХранилища(АдресХранилища, "имя_файла.txt");
        Предупреждение("Файл успешно загружен на сервер!");
    КонецЕсли;
КонецПроцедуры

Важный нюанс: Чтобы данные во временном хранилище "жили" достаточно долго, в качестве параметра УникальныйИдентификатор нужно передавать идентификатор текущей формы. Это гарантирует, что файл будет доступен до тех пор, пока форма не будет закрыта.

Метод 2: Передача через объект ДвоичныеДанные (без хранилища)

Если по каким-то причинам вы не хотите использовать временное хранилище, можно воспользоваться объектом ДвоичныеДанные. Этот метод прост, но имеет ограничение: он потребляет значительный объем оперативной памяти, так как файл полностью считывается в переменную.

Разберем этот способ:

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

Пример реализации:


// Код в модуле формы (Клиент)
ПутьКФайлу = "C:\MyFiles\report.pdf";
ДанныеФайла = Новый ДвоичныеДанные(ПутьКФайлу);

// Вызов серверного общего модуля
РаботаСФайламиСервер.ЗаписатьФайлНаСервер(ДанныеФайла, "report_server.pdf");

Метод 3: Использование COM-объектов для прямого копирования

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


FSO = Новый COMОбъект("Scripting.FileSystemObject");
Попытка
    FSO.CopyFile("C:\local\file.txt", "\\ServerName\SharedFolder\file.txt", Истина);
Исключение
    Сообщить("Ошибка копирования: " + ОписаниеОшибки());
КонецПопытки;

Внимание: Этот метод менее надежен, так как сильно зависит от настроек прав доступа Windows и сетевой связности, которые часто блокируются политиками безопасности.

Настройка серверного модуля

Чтобы методы, описанные выше, действительно сработали "на сервере", необходимо правильно настроить Общий модуль. Проанализируем необходимые свойства модуля:

Пример серверного кода в общем модуле РаботаСФайламиСервер:


Процедура СохранитьФайлИзХранилища(АдресХранилища, ИмяФайла) Экспорт
    // Получаем данные из временного хранилища
    Данные = ПолучитьИзВременногоХранилища(АдресХранилища);
    
    // Формируем путь на диске СЕРВЕРА
    ПутьНаСервере = "D:\Storage\" + ИмяФайла;
    
    // Записываем файл на диск
    Данные.Записать(ПутьНаСервере);
КонецПроцедуры

Проблемы прав доступа и путей

Рассмотрим типичные ошибки при реализации загрузки файлов:

1. Права службы 1С: При выполнении кода на сервере, запись на диск происходит от имени учетной записи, под которой запущена служба 1C:Enterprise 8.3 Server Agent (обычно это USR1CV8). У этой учетной записи должны быть права на запись в целевую папку на сервере.

2. Локальные пути: Помните, что путь C:\Temp в серверном коде — это папка на системном диске сервера, а не на компьютере пользователя. Всегда проверяйте существование каталогов перед записью.

3. Файловый режим: Если ваша база работает в файловом режиме, то разделение на клиент и сервер чисто номинальное. Файл будет сохранен на том же компьютере, где запущен клиент, просто в указанную папку.

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

← На главную