При переходе с тонкого клиента на веб-клиент разработчики часто сталкиваются с ошибкой "Метод объекта не обнаружен (Записать)" или проблемами при попытке использовать временные файлы. Это происходит из-за того, что архитектура веб-клиента накладывает жесткие ограничения на доступ к локальной файловой системе пользователя из соображений безопасности браузеров. В этой статье мы подробно разберем, почему привычные методы не работают в браузере и как правильно организовать работу с файлами, чтобы она была стабильной и удобной для пользователя.
Рассмотрим ситуацию: у нас есть объект типа ДвоичныеДанные, и мы пытаемся вызвать метод Записать() на стороне клиента. В тонком клиенте это работает без проблем, так как приложение имеет прямой доступ к файловой системе ОС. Однако, если мы заглянем в синтакс-помощник, то увидим, что в разделе "Доступность" для этого метода отсутствует "Веб-клиент".
Проанализируем основные ограничения веб-клиента:
"C:\Temp\file.docx". Браузер работает в изолированной среде ("песочнице").Если нам критически важно записать файл по конкретному пути или взаимодействовать с локальными приложениями напрямую, нам потребуется Расширение работы с файлами. Выясним, как это реализовать программно. Вместо синхронного метода Записать() мы должны использовать НачатьЗапись().
Рассмотрим пример кода, который проверяет наличие расширения и пытается записать данные:
&НаКлиенте
Процедура СохранитьФайлСРасширением(ДанныеФайла, ПутьСохранения)
#Если ВебКлиент Тогда
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеПодключенияРасширения", ЭтотОбъект, ДанныеФайла);
НачатьПодключениеРасширенияРаботыСФайлами(ОписаниеОповещения);
#КонецЕсли
КонецПроцедуры
&НаКлиенте
Процедура ПослеПодключенияРасширения(Подключено, ДополнительныеПараметры) Экспорт
Если Подключено Тогда
// Используем асинхронную запись
Данные = ДополнительныеПараметры;
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗаписиФайла", ЭтотОбъект);
Данные.НачатьЗапись(ОписаниеОповещения, "C:\MyFiles\document.docx");
Иначе
Сообщить("Для записи файла необходимо установить расширение браузера.");
НачатьУстановкуРасширенияРаботыСФайлами();
КонецЕсли;
КонецПроцедуры
Важно понимать, что этот подход в 2024 году становится все менее популярным из-за того, что пользователи неохотно устанавливают дополнительные компоненты в браузер, а политики безопасности Chrome или Edge могут блокировать такие действия.
Это самый надежный и современный способ, который работает во всех браузерах без установки каких-либо расширений. Вместо того чтобы пытаться "насильно" записать файл на диск, мы предлагаем браузеру скачать его, как любой другой файл из интернета.
Разберем алгоритм действий по шагам:
ВременноеХранилище и получим адрес.НачатьПолучениеФайлаССервера().Посмотрим на пример реализации:
&НаКлиенте
Процедура ВыполнитьПечать(ИмяМакета)
// Получаем адрес временного хранилища с сервера
Результат = ПодготовитьФайлНаСервере(ИмяМакета);
ПараметрыДиалога = Новый ПараметрыДиалогаПолученияФайлов;
// Файл будет скачан стандартными средствами браузера в папку "Загрузки"
НачатьПолучениеФайлаССервера(Результат.Адрес, Результат.ИмяФайла, ПараметрыДиалога);
КонецПроцедуры
&НаСервере
Функция ПодготовитьФайлНаСервере(ИмяМакета)
Макет = УправлениеПечатью.Макет(ИмяМакета); // Пример получения макета
// Предположим, Макет уже является объектом ДвоичныеДанные
Адрес = ПоместитьВоВременноеХранилище(Макет, ЭтаФорма.УникальныйИдентификатор);
Возврат Новый Структура("Адрес, ИмяФайла", Адрес, "Документ.docx");
КонецФункции
В этом случае пользователю не нужно ничего устанавливать. Браузер просто покажет диалог сохранения или автоматически поместит файл в папку загрузок. Это максимально безопасный и стабильный вариант для веб-клиента.
Если вы работаете на платформе версии 8.3.18 и выше, мы рекомендуем отказаться от сложных ОписаниеОповещения в пользу асинхронных функций. Это сделает ваш код линейным и читаемым. Проанализируем, как изменится код для получения файла:
&НаКлиенте
Асинхрон Процедура СохранитьФайлСовременно(ИмяМакета)
РезультатСервер = Ждать ПодготовитьФайлНаСервереАсинхрон(ИмяМакета);
// Вместо НачатьПолучение... используем ПолучитьФайлССервераАсинхрон
Ждать ПолучитьФайлССервераАсинхрон(РезультатСервер.Адрес, РезультатСервер.ИмяФайла);
КонецПроцедуры
Использование ключевых слов Асинхрон и Ждать значительно упрощает разработку под веб-клиент, устраняя необходимость плодить множество мелких процедур для обратных вызовов.
Часто задача звучит не просто "записать", а "открыть файл для редактирования". В тонком клиенте мы используем ЗапуститьПриложение. В веб-клиенте это невозможно сделать напрямую без расширения.
Рассмотрим альтернативы:
НачатьПолучениеФайлаССервера, пользователь сам открывает его из панели загрузок браузера.Таким образом, для работы в веб-клиенте мы должны полностью сменить парадигму с "прямой записи на диск" на "передачу файла через хранилище и скачивание средствами браузера". Это обеспечит кроссбраузерность и избавит от ошибок, связанных с правами доступа и отсутствием методов в веб-клиенте.