Почему в веб-клиенте 1С не срабатывает оповещение при вызове НачатьПомещениеФайла и как это исправить

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

При разработке в среде 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда код, идеально работающий в тонком клиенте, начинает вести себя непредсказуемо в веб-клиенте. Одной из классических проблем является «молчаливое» невыполнение процедур обратного вызова (оповещений) после интерактивного выбора файлов. Пользователь выбирает файл в диалоговом окне браузера, нажимает кнопку открытия, но далее ничего не происходит: процедура обратного вызова, переданная в ОписаниеОповещения, попросту не запускается.

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

Проанализируем детально причины этой проблемы и пути ее решения.

Причина 1. Уничтожение контекста формы внешней обработки в веб-клиенте

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

Когда вы запускаете внешнюю обработку (особенно через механизм дополнительных отчетов и обработок БСП) в тонком клиенте, платформа удерживает в оперативной памяти весь контекст формы и модуля до тех пор, пока не завершится асинхронный процесс. В веб-клиенте ситуация иная:

  1. При вызове метода НачатьПомещениеФайла управление моментально передается браузеру для отображения системного диалога выбора файлов.
  2. Для веб-клиента выполнение текущего потока команд завершается. Сама внешняя обработка, если она была открыта немодально или вызвана динамически, завершает свою работу на клиенте.
  3. Браузерный сборщик мусора (Garbage Collector), обнаружив, что явных жестких ссылок на экземпляр формы внешней обработки в активном пуле выполнения не осталось, выгружает объект формы ЭтаФорма из памяти.
  4. Когда пользователь наконец выбирает файл в диалоговом окне и подтверждает выбор, браузер пытается передать управление обратно в процедуру оповещения, адрес которой связан с контекстом уничтоженной формы. Так как целевой объект ЭтаФорма больше не существует, вызов аннулируется без генерации системных ошибок.

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

Причина 2. Ограничения безопасного режима и веб-безопасности

Внешние обработки в современных конфигурациях по умолчанию запускаются в безопасном режиме. Это накладывает серьезные ограничения на работу с файловой системой. В веб-клиенте эти ограничения удваиваются требованиями безопасности самого браузера (песочницей JavaScript). Браузер блокирует попытки совершения небезопасных асинхронных операций, исходящих от динамически загружаемых скриптов, которыми, по сути, и являются формы внешних обработок. Использование расширений конфигурации позволяет выполнять код в доверенном контексте, снимая данные ограничения.

Причина 3. Использование устаревших методов и требования к расширению браузера

Если в вашем коде используется метод НачатьПомещениеФайла совместно с объектом ДиалогВыбораФайла, веб-клиент будет настойчиво требовать установки специального расширения работы с файлами для браузера (компоненты extra-файлов). В современных браузерах (Google Chrome, Firefox, Opera последних версий) поддержка старых технологий плагинов (NPAPI) полностью прекращена. Попытка установить расширение работы с файлами часто превращается в бесконечный цикл: платформа просит установить расширение, пользователь соглашается, но браузер блокирует его интеграцию, и оповещение снова не отрабатывает.

Начиная с версии 8.3.15, фирма «1С» кардинально переработала механизмы работы с файловой системой в веб-клиенте. Метод НачатьПомещениеФайла признан устаревшим.

Рассмотрим, как выглядит устаревший код, который приводит к сбоям на веб-клиенте:


// ПРИМЕР КОДА, КОТОРЫЙ ВЫЗЫВАЕТ ОШИБКИ В ВЕБ-КЛИЕНТЕ
&НаКлиенте
Процедура ЗагрузитьФайлСтарымСпособом(Команда)
    
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Диалог.Заголовок = "Выберите файл для загрузки";
    
    ОбработкаОкончанияЗагрузки = Новый ОписаниеОповещения("Обработчик_Завершения_Загрузки", ЭтаФорма, Диалог);
    
    // Этот метод устарел и требует установки расширения браузера
    НачатьПомещениеФайла(ОбработкаОкончанияЗагрузки, , Диалог, Истина, УникальныйИдентификатор);
    
КонецПроцедуры

&НаКлиенте
Процедура Обработчик_Завершения_Загрузки(Результат, Адрес, ВыбранноеИмяФайла, ДополнительныеПараметры) Экспорт
    // В веб-клиенте этот код во внешней обработке часто вообще не выполняется!
    Если Результат Тогда
        ПоказатьПредупреждение(, "Файл успешно загружен: " + ВыбранноеИмяФайла);
    КонецЕсли;
EndПроцедуры

Выясним, как переписать этот алгоритм под современные стандарты платформы, чтобы он гарантированно работал в любом браузере без установки дополнительных компонентов.

Современное решение: Переход на НачатьПомещениеФайлаНаСервер

Для того чтобы обойти ограничения веб-клиента и избавиться от необходимости устанавливать расширение работы с файлами, мы должны использовать метод НачатьПомещениеФайлаНаСервер. Этот метод использует стандартный HTML5 File API вашего браузера, что делает процедуру выбора файла абсолютно нативной и безопасной.

Разберем по шагам правильную реализацию загрузки файла, которая будет стабильно работать как в тонком, так и в веб-клиенте (включая внешние обработки, если они корректно удерживают фокус).

Вместо объекта ДиалогВыбораФайла мы применим специальный класс ПараметрыДиалогаПомещенияФайлов.


&НаКлиенте
Процедура ЗагрузитьФайлСовременно(Команда)
    
    // Создаем параметры диалога вместо старого ДиалогВыбораФайла
    ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
    ПараметрыДиалога.МножественныйВыбор = Ложь;
    ПараметрыДиалога.Заголовок = "Выберите файл для импорта в систему";
    ПараметрыДиалога.Фильтр = "Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*";
    
    // Описываем оповещение, указывая экспортную процедуру текущей формы
    ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВыбораФайлаНаСервер", ЭтаФорма);
    
    // Запускаем асинхронное помещение файла на сервер. 
    // Данный метод НЕ требует установки расширения работы с файлами в браузере!
    НачатьПомещениеФайлаНаСервер(ОписаниеОповещения, , , ПараметрыДиалога, УникальныйИдентификатор);
    
КонецПроцедуры

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

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

Альтернативное решение: Использование расширений конфигурации для сохранения контекста

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

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

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


&НаКлиенте
Процедура ОткрытьФормуОбработкиДляЗагрузки(Команда)
    
    // Вместо работы в контексте "непривязанной" внешней обработки,
    // откроем форму явно через менеджер окон платформы
    ПараметрыФормы = Новый Структура;
    ОткрытьФорму("ВнешняяОбработка.МояЗагрузкаДанных.Форма.ФормаЗагрузки", ПараметрыФормы, ЭтаФорма, Истина);
    
КонецПроцедуры

Специфический баг веб-клиента с фильтрами файлов

При использовании нового класса ПараметрыДиалогаПомещенияФайлов в веб-клиенте разработчики иногда сталкиваются с неприятным багом: в системном окне выбора файлов кнопка «Открыть» («ОК») становится серой (неактивной) после выбора нужного файла. Это происходит из-за некорректной интерпретации маски фильтра расширений в некоторых браузерах.

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


// Если кнопка выбора блокируется, упростите фильтр:
ПараметрыДиалога.Фильтр = "Все файлы (*.*)|*.*";

Подведем итог. Стабильная работа с файлами в веб-клиенте 1С строится на трех правилах: использование асинхронных методов версии платформы 8.3.15+ (таких как НачатьПомещениеФайлаНаСервер), отказ от использования устаревших модальных окон и диалогов, а также обеспечение гарантированного выживания контекста формы на время ожидания ответа пользователя.

← На главную