При разработке под управляемый интерфейс 1С:Предприятия часто возникает задача загрузки объемных файлов (архивов, дампов баз, медиафайлов размером от сотен мегабайт до нескольких гигабайт) с клиентского рабочего места на сервер. Разработчики нередко рассчитывают на штатные асинхронные методы платформы, однако на практике сталкиваются с полным зависанием интерфейса формы на время передачи данных.
Разберем детально, почему так происходит, какие ограничения заложены в архитектуру клиентского приложения 1С и какими способами можно организовать передачу больших файлов без блокировки работы пользователя.
Проанализируем работу штатных механизмов помещения файлов, таких как ПоместитьФайлНаСерверАсинх(), ПоместитьФайлыНаСерверАсинх() или устаревший метод НачатьПомещениеФайла():
Асинх и Ждать освобождают стек вызовов, но не выделяют отдельный системный поток операционной системы для сетевого обмена. Вся передача данных происходит внутри процесса клиента.ДвоичныеДанные или поместить его во временное хранилище весь объем данных выгружается в оперативную память клиентского процесса и серверного процесса rphost. Для 32-разрядных клиентов это практически гарантированно приводит к критической ошибке нехватки памяти.Таким образом, организовать полностью независимую фоновую передачу файлов объемом около 1 ГБ исключительно через стандартное помещение во временное хранилище в текущем сеансе невозможно. Рассмотрим проверенные архитектурные альтернативы.
Самый простой и надежный подход для работы внутри локальной корпоративной сети — исключить передачу тяжелых данных через внутренний транспорт 1С.
Разберем алгоритм по шагам:
КопироватьФайлАсинх() или через внешний командный скрипт копирует файл в сетевой каталог, назначая ему уникальное временное имя (например, с использованием Строка(Новый УникальныйИдентификатор())).ФоновыеЗадания.Посмотрим на пример вызова фонового задания на сервере:
&НаСервере
Процедура ЗапуститьОбработкуФайлаНаСервере(ПутьКФайлуВСети)
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ПутьКФайлуВСети);
ФоновыеЗадания.Выполнить(
"ИнтеграцияСервер.ОбработатьЗагруженныйФайл",
ПараметрыЗадания,
Строка(Новый УникальныйИдентификатор()),
"Обработка большого файла"
);
КонецПроцедуры
Если прямого сетевого доступа к файловой системе сервера у пользователей нет (например, работа идет через интернет или распределенные филиалы), передачу можно вынести в отдельный процесс операционной системы, настроив прием данных через HTTP-сервис 1С.
Схема работы выглядит следующим образом:
ФайловыйПоток (чтобы не переполнять оперативную память процесса rphost).curl или собственный скрипт), которая отправляет файл методом POST или PUT отдельным независимым системным процессом.ЗапуститьПриложениеАсинх().Посмотрим на пример формирования команды для фоновой отправки:
&НаКлиенте
Асинх Процедура ОтправитьФайлВФоне(ПутьКФайлу, ТокенАвторизации)
АдресСервиса = "https://1c.company.ru/base/hs/files/upload";
КомандаЗапуска = СтрШаблон(
"curl -X POST --data-binary ""@%1"" -H ""Authorization: Bearer %2"" ""%3""",
ПутьКФайлу,
ТокенАвторизации,
АдресСервиса
);
// Запуск процесса без ожидания завершения (интерфейс 1С свободен)
Оповещение = Новый ОписаниеОповещения("ПослеЗапускаПередачи", ЭтотОбъект);
ЗапуститьПриложение(КомандаЗапуска, , Ложь, 0);
КонецПроцедуры
Для высоконагруженных систем стандартом является архитектура прямой загрузки (Direct Upload), минуя кластер серверов 1С:
Если требуется полностью бесшовный интерфейс внутри тонкого клиента без сторонних консольных окон, оптимальным решением выступает разработка или подключение внешней компоненты, созданной по технологии Native API (на C++, Rust или C#):
ОбработкаВнешнегоСобытия формы или модуля управляемого приложения.При использовании любого из асинхронных вариантов передачи данных серверу необходимо уведомить пользователя о завершении загрузки и обработки. Чтобы не нагружать клиент циклическими опросами сервера по таймеру (обработками ожидания), рекомендуется использовать штатный механизм Системы взаимодействия:
// Серверный код фонового задания после обработки файла
Сообщение = СистемаВзаимодействия.СоздатьСообщение();
Сообщение.Получатели.Добавить(ПользовательИнициатор);
Сообщение.Текст = "Файл успешно загружен и обработан сервером.";
Сообщение.Записать();
Такой подход позволяет передавать тяжелые файлы без блокировки пользовательского интерфейса и обеспечивает масштабируемую архитектуру взаимодействия клиента и сервера.