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

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

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

Разберем по шагам причины медленной работы при передаче двоичных данных, выясним особенности сериализации платформы и рассмотрим проверенные способы оптимизации клиент-серверного взаимодействия.

Почему кэширование во временном хранилище может работать медленно

Проанализируем ситуацию: разработчик помещает коллекцию (например, Соответствие или Структура), содержащую объекты ДвоичныеДанные, во временное хранилище с привязкой к сеансу и сохраняет полученный адрес. Однако вызовы все равно занимают много времени. Выделим основные технические причины такого поведения:

  1. Накладные расходы на сериализацию коллекций: если в ПоместитьВоВременноеХранилище передается сложный объект (соответствие с десятками файлов), платформа тратит значительные ресурсы процессора на упаковку и распаковку каждого бинарного объекта.
  2. Контекстные серверные вызовы: при вызове процедур и функций с директивой &НаСервере на сервер неявно передаются все реквизиты текущей формы, а при возврате — отправляются обратно на клиент. Если данные формы раздуты, контекст замедляет каждый вызов независимо от хранилища.
  3. Передача параметров по ссылке: если серверная процедура принимает параметры без ключевого слова Знач, платформа сериализует их обратно на клиент после завершения вызова, даже если они не изменялись.
  4. Вызов получения данных на клиенте: метод ПолучитьИзВременногоХранилища, вызванный на клиенте, инициирует физическую загрузку всех двоичных данных по сети с сервера на клиентскую машину.
  5. Неконтролируемое заполнение памяти: использование Новый УникальныйИдентификатор привязывает данные к жизни всего сеанса пользователя. В результате процесс rphost держит бинарные данные в оперативной памяти вплоть до закрытия программы, что создает дополнительную нагрузку на кластер серверов.

Способ 1. Архивация файлов перед отправкой (ZIP-сжатие)

Рассмотрим один из самых эффективных способов снижения объема передаваемых по сети данных — предварительное сжатие файлов на стороне клиента с помощью объекта ЗаписьZipФайла.

Текстовые файлы, документы XML, JSON и выгрузки CSV отлично сжимаются, что позволяет уменьшить сетевой трафик в 5–10 раз. Посмотрим на пример кода подготовки архива на клиенте и его распаковки на сервере:


&НаКлиенте
Процедура ОтправитьСжатыеФайлыНаСервер(МассивПутейКФайлам)
    
    ИмяАрхива = ПолучитьИмяВременногоФайла("zip");
    
    Архиватор = Новый ЗаписьZipФайла(ИмяАрхива);
    Для Каждого ПутьКФайлу Из МассивПутейКФайлам Цикл
        Архиватор.Добавить(ПутьКФайлу, РежимСохраненияПутейZIP.НеСохранятьПути);
    КонецЦикла;
    Архиватор.Записать();
    
    ДвоичныеДанныеАрхива = Новый ДвоичныеДанные(ИмяАрхива);
    УдалитьФайлы(ИмяАрхива);
    
    АдресАрхива = ПоместитьВоВременноеХранилище(ДвоичныеДанныеАрхива, УникальныйИдентификатор);
    
    ОбработатьАрхивНаСервереБезКонтекста(АдресАрхива);
    
    УдалитьИзВременногоХранилища(АдресАрхива);
    
КонецПроцедуры

На стороне сервера выполняем чтение архива и извлечение необходимых файлов:


&НаСервереБезКонтекста
Процедура ОбработатьАрхивНаСервереБезКонтекста(Знач АдресАрхива)
    
    ДвоичныеДанныеАрхива = ПолучитьИзВременногоХранилища(АдресАрхива);
    
    ИмяВременногоАрхива = ПолучитьИмяВременногоФайла("zip");
    ДвоичныеДанныеАрхива.Записать(ИмяВременногоАрхива);
    
    КаталогРаспаковки = КаталогВременныхФайлов() + "Unpack_" + СтрЗаменить(Строка(Новый УникальныйИдентификатор), "-", "");
    СоздатьКаталог(КаталогРаспаковки);
    
    ЧтениеАрхива = Новый ЧтениеZipФайла(ИмяВременногоАрхива);
    ЧтениеАрхива.ИзвлечьВсе(КаталогРаспаковки, РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
    ЧтениеАрхива.Закрыть();
    
    // Обрабатываем извлеченные файлы из КаталогРаспаковки
    
    // Обязательно очищаем временные файлы на сервере
    УдалитьФайлы(ИмяВременногоАрхива);
    УдалитьФайлы(КаталогРаспаковки);
    
КонецПроцедуры

Способ 2. Оптимизация контекста и передача параметров по значению

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

  1. Используйте директиву &НаСервереБезКонтекста: если для обработки файла не требуются элементы и реквизиты текущей формы, всегда используйте вызовы без контекста. Это предотвращает сериализацию данных формы.
  2. Передавайте параметры со словом Знач: чтобы платформа не возвращала переданную строку адреса хранилища или структуры обратно на клиент, указывайте Знач ИмяПараметра в сигнатуре серверной процедуры или функции.
  3. Привязывайте временное хранилище к форме: вместо передачи Новый УникальныйИдентификатор передавайте УникальныйИдентификатор формы. В этом случае данные автоматически удалятся из оперативной памяти сервера при закрытии окна пользователем.
  4. Явно вызывайте УдалитьИзВременногоХранилища: сразу после того, как двоичные данные прочитаны на сервере, очищайте хранилище вручную.

Способ 3. Использование временных файлов на сервере

Когда требуется работать с файлами большого объема (например, базами SQLite, большими логами или тяжелыми таблицами), хранить их в оперативной памяти процессов rphost в виде объектов ДвоичныеДанные не рекомендуется. Оптимальным решением является сохранение на диск сервера во временный файл.

Посмотрим на пример безопасной работы с временным файлом:


&НаСервереБезКонтекста
Процедура ЗагрузитьДанныеИзХранилищаНаСервере(Знач АдресВХранилище)
    
    ПутьВременногоФайла = ПолучитьИмяВременногоФайла();
    
    Попытка
        ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресВХранилище);
        ДвоичныеДанные.Записать(ПутьВременногоФайла);
        
        // Выполняем чтение и обработку файла на сервере
        
    Исключение
        УдалитьФайлы(ПутьВременногоФайла);
        ВызватьИсключение;
    КонецПопытки;
    
    УдалитьФайлы(ПутьВременногоФайла);
    
КонецПроцедуры

Способ 4. Асинхронная потоковая загрузка файлов

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

Использование встроенных асинхронных методов исключает ручное создание объектов ДвоичныеДанные в коде клиента и снижает пиковую нагрузку на оперативную память.

Альтернативные архитектурные решения

Если специфика задачи предполагает регулярный обмен тяжелыми файлами между рабочими местами и сервером 1С, рассмотрим альтернативные варианты архитектуры:

  1. Общий сетевой ресурс (Shared Folder / UNC): если клиент и сервер находятся в локальной сети, файлы можно сохранять в общую сетевую папку (например, \\server\share\data.xml). Сервер 1С обращается к файлу напрямую по сетевому пути, полностью минуя транспортный протокол платформы 1С.
  2. Общие модули с повторным использованием значений: если файл содержит неизменяемые справочные данные, результат его разбора можно кэшировать в функции общего модуля с установленным свойством «Повторное использование возвращаемых значений» («На время сеанса» или «На время вызова»). Это исключит повторные обращения к диску и хранилищу.
← На главную